/* $Id: CoinAbcBaseFactorization4.cpp 2385 2019-01-06 19:43:06Z unxusr $ */
// Copyright (C) 2002, International Business Machines
// Corporation and others, Copyright (C) 2012, FasterCoin.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#ifdef ABC_JUST_ONE_FACTORIZATION
#include "CoinAbcCommonFactorization.hpp"
#define CoinAbcTypeFactorization CoinAbcBaseFactorization
#define ABC_SMALL -1
#include "CoinAbcBaseFactorization.hpp"
#endif
#ifdef CoinAbcTypeFactorization

#include "CoinIndexedVector.hpp"
#include "CoinHelperFunctions.hpp"
#include "CoinAbcHelperFunctions.hpp"
#if CILK_CONFLICT > 0
// for conflicts
extern int cilk_conflict;
#endif

//:class CoinAbcTypeFactorization.  Deals with Factorization and Updates
#if ABC_SMALL < 2
//  getColumnSpaceIterateR.  Gets space for one extra R element in Column
//may have to do compression  (returns true)
//also moves existing vector
bool CoinAbcTypeFactorization::getColumnSpaceIterateR(CoinSimplexInt iColumn, CoinFactorizationDouble value,
  CoinSimplexInt iRow)
{
  CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_ + lengthAreaR_;
  CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_ + lengthAreaR_;
  CoinBigIndex *COIN_RESTRICT startR = startColumnRAddress_ + maximumPivots_ + 1;
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
  CoinSimplexInt number = numberInColumnPlus[iColumn];
  //*** modify so sees if can go in
  //see if it can go in at end
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;
  if (lengthAreaR_ - startR[maximumRowsExtra_] < number + 1) {
    //compression
    CoinSimplexInt jColumn = nextColumn[maximumRowsExtra_];
    CoinBigIndex put = 0;
    while (jColumn != maximumRowsExtra_) {
      //move
      CoinBigIndex get;
      CoinBigIndex getEnd;
      get = startR[jColumn];
      getEnd = get + numberInColumnPlus[jColumn];
      startR[jColumn] = put;
      CoinBigIndex i;
      for (i = get; i < getEnd; i++) {
        indexRowR[put] = indexRowR[i];
        elementR[put] = elementR[i];
        put++;
      }
      jColumn = nextColumn[jColumn];
    }
    numberCompressions_++;
    startR[maximumRowsExtra_] = put;
  }
  // Still may not be room (as iColumn was still in)
  if (lengthAreaR_ - startR[maximumRowsExtra_] < number + 1)
    return false;

  CoinSimplexInt next = nextColumn[iColumn];
  CoinSimplexInt last = lastColumn[iColumn];
  //out
  nextColumn[last] = next;
  lastColumn[next] = last;

  CoinBigIndex put = startR[maximumRowsExtra_];
  //in at end
  last = lastColumn[maximumRowsExtra_];
  nextColumn[last] = iColumn;
  lastColumn[maximumRowsExtra_] = iColumn;
  lastColumn[iColumn] = last;
  nextColumn[iColumn] = maximumRowsExtra_;

  //move
  CoinBigIndex get = startR[iColumn];
  startR[iColumn] = put;
  CoinSimplexInt i = 0;
  for (i = 0; i < number; i++) {
    elementR[put] = elementR[get];
    indexRowR[put++] = indexRowR[get++];
  }
  //insert
  elementR[put] = value;
  indexRowR[put++] = iRow;
  numberInColumnPlus[iColumn]++;
  //add 4 for luck
  startR[maximumRowsExtra_] = CoinMin(static_cast< CoinBigIndex >(put + 4), lengthAreaR_);
  return true;
}
#endif
CoinSimplexInt CoinAbcTypeFactorization::checkPivot(CoinSimplexDouble saveFromU,
  CoinSimplexDouble oldPivot) const
{
  CoinSimplexInt status;
  if (fabs(saveFromU) > 1.0e-8) {
    CoinFactorizationDouble checkTolerance;
    if (numberRowsExtra_ < numberRows_ + 2) {
      checkTolerance = 1.0e-5;
    } else if (numberRowsExtra_ < numberRows_ + 10) {
      checkTolerance = 1.0e-6;
    } else if (numberRowsExtra_ < numberRows_ + 50) {
      checkTolerance = 1.0e-8;
    } else {
      checkTolerance = 1.0e-10;
    }
    checkTolerance *= relaxCheck_;
    if (fabs(1.0 - fabs(saveFromU / oldPivot)) < checkTolerance) {
      status = 0;
    } else {
#if COIN_DEBUG
      std::cout << "inaccurate pivot " << oldPivot << " "
                << saveFromU << std::endl;
#endif
      if (fabs(fabs(oldPivot) - fabs(saveFromU)) < 1.0e-12 || fabs(1.0 - fabs(saveFromU / oldPivot)) < 1.0e-8) {
        status = 1;
      } else {
        status = 2;
      }
    }
  } else {
    //error
    status = 2;
#if COIN_DEBUG
    std::cout << "inaccurate pivot " << saveFromU / oldPivot
              << " " << saveFromU << std::endl;
#endif
  }
  return status;
}
#define INLINE_IT
#define INLINE_IT2
#define INLINE_IT3
#define UNROLL 0
inline void scatterUpdateInline(CoinSimplexInt number,
  CoinFactorizationDouble pivotValue,
  const CoinFactorizationDouble *COIN_RESTRICT thisElement,
  const CoinSimplexInt *COIN_RESTRICT thisIndex,
  CoinFactorizationDouble *COIN_RESTRICT region)
{
#if UNROLL == 0
  for (CoinBigIndex j = number - 1; j >= 0; j--) {
    CoinSimplexInt iRow = thisIndex[j];
    CoinFactorizationDouble regionValue = region[iRow];
    CoinFactorizationDouble value = thisElement[j];
    assert(value);
    region[iRow] = regionValue - value * pivotValue;
  }
#elif UNROLL == 1
  if ((number & 1) != 0) {
    number--;
    CoinSimplexInt iRow = thisIndex[number];
    CoinFactorizationDouble regionValue = region[iRow];
    CoinFactorizationDouble value = thisElement[number];
    region[iRow] = regionValue - value * pivotValue;
  }
  for (CoinBigIndex j = number - 1; j >= 0; j -= 2) {
    CoinSimplexInt iRow0 = thisIndex[j];
    CoinSimplexInt iRow1 = thisIndex[j - 1];
    CoinFactorizationDouble regionValue0 = region[iRow0];
    CoinFactorizationDouble regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[j] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[j - 1] * pivotValue;
  }
#elif UNROLL == 2
  CoinSimplexInt iRow0;
  CoinSimplexInt iRow1;
  CoinFactorizationDouble regionValue0;
  CoinFactorizationDouble regionValue1;
  switch (number) {
  case 0:
    break;
  case 1:
    iRow0 = thisIndex[0];
    regionValue0 = region[iRow0];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    break;
  case 2:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    break;
  case 3:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    iRow0 = thisIndex[2];
    regionValue0 = region[iRow0];
    region[iRow0] = regionValue0 - thisElement[2] * pivotValue;
    break;
  case 4:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    iRow0 = thisIndex[2];
    iRow1 = thisIndex[3];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[2] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[3] * pivotValue;
    break;
  case 5:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    iRow0 = thisIndex[2];
    iRow1 = thisIndex[3];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[2] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[3] * pivotValue;
    iRow0 = thisIndex[4];
    regionValue0 = region[iRow0];
    region[iRow0] = regionValue0 - thisElement[4] * pivotValue;
    break;
  case 6:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    iRow0 = thisIndex[2];
    iRow1 = thisIndex[3];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[2] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[3] * pivotValue;
    iRow0 = thisIndex[4];
    iRow1 = thisIndex[5];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[4] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[5] * pivotValue;
    break;
  case 7:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    iRow0 = thisIndex[2];
    iRow1 = thisIndex[3];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[2] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[3] * pivotValue;
    iRow0 = thisIndex[4];
    iRow1 = thisIndex[5];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[4] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[5] * pivotValue;
    iRow0 = thisIndex[6];
    regionValue0 = region[iRow0];
    region[iRow0] = regionValue0 - thisElement[6] * pivotValue;
    break;
  case 8:
    iRow0 = thisIndex[0];
    iRow1 = thisIndex[1];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[0] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[1] * pivotValue;
    iRow0 = thisIndex[2];
    iRow1 = thisIndex[3];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[2] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[3] * pivotValue;
    iRow0 = thisIndex[4];
    iRow1 = thisIndex[5];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[4] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[5] * pivotValue;
    iRow0 = thisIndex[6];
    iRow1 = thisIndex[7];
    regionValue0 = region[iRow0];
    regionValue1 = region[iRow1];
    region[iRow0] = regionValue0 - thisElement[6] * pivotValue;
    region[iRow1] = regionValue1 - thisElement[7] * pivotValue;
    break;
  default:
    if ((number & 1) != 0) {
      number--;
      CoinSimplexInt iRow = thisIndex[number];
      CoinFactorizationDouble regionValue = region[iRow];
      CoinFactorizationDouble value = thisElement[number];
      region[iRow] = regionValue - value * pivotValue;
    }
    for (CoinBigIndex j = number - 1; j >= 0; j -= 2) {
      CoinSimplexInt iRow0 = thisIndex[j];
      CoinSimplexInt iRow1 = thisIndex[j - 1];
      CoinFactorizationDouble regionValue0 = region[iRow0];
      CoinFactorizationDouble regionValue1 = region[iRow1];
      region[iRow0] = regionValue0 - thisElement[j] * pivotValue;
      region[iRow1] = regionValue1 - thisElement[j - 1] * pivotValue;
    }
    break;
  }
#endif
}
inline CoinFactorizationDouble gatherUpdate(CoinSimplexInt number,
  const CoinFactorizationDouble *COIN_RESTRICT thisElement,
  const CoinSimplexInt *COIN_RESTRICT thisIndex,
  CoinFactorizationDouble *COIN_RESTRICT region)
{
  CoinFactorizationDouble pivotValue = 0.0;
  for (CoinBigIndex j = 0; j < number; j++) {
    CoinFactorizationDouble value = thisElement[j];
    CoinSimplexInt jRow = thisIndex[j];
    value *= region[jRow];
    pivotValue -= value;
  }
  return pivotValue;
}
inline void multiplyIndexed(CoinSimplexInt number,
  const CoinFactorizationDouble *COIN_RESTRICT multiplier,
  const CoinSimplexInt *COIN_RESTRICT thisIndex,
  CoinFactorizationDouble *COIN_RESTRICT region)
{
  for (CoinSimplexInt i = 0; i < number; i++) {
    CoinSimplexInt iRow = thisIndex[i];
    CoinSimplexDouble value = region[iRow];
    value *= multiplier[iRow];
    region[iRow] = value;
  }
}
#if 0
/* Checks if can replace one Column to basis,
   returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots
   Fills in region for use later
   partial update already in U */
int 
CoinAbcTypeFactorization::checkReplace ( const AbcSimplex * model,
					 CoinIndexedVector * regionSparse,
					 int pivotRow,
					 CoinSimplexDouble &pivotCheck,
					 double acceptablePivot)
{
  if ( lengthR_+numberRows_ >= lengthAreaR_ ) {
    //not enough room
    return 3;
  }
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
  CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
  CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
  CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU;
  CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast<CoinSimplexInt *>(elementU2+numberInColumnU2);
#else
  CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_;
  CoinBigIndex startU = startColumnU[numberRows_];
  CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_];
#endif
  if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) {
    //not enough room
    return 3;
  }
#if ABC_SMALL < 2
  CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
  //zeroed out region
  CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse);
  CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  CoinFactorizationDouble oldPivot = pivotRegion[pivotRow];
  // for accuracy check
  pivotCheck = pivotCheck / oldPivot;

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex saveStart = startColumnU[pivotRow];
  CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow];
#endif
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
  CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#if CONVERTROW > 2
  CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices (  );
  CoinSimplexInt status=0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *  COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif

#ifndef NDEBUG
#if CONVERTROW
#define CONVERTDEBUG
#endif
#endif
  int nInRow;
#if ABC_SMALL < 2
  CoinBigIndex start=0;
  CoinBigIndex end=0;
  if (gotUCopy()) {
    start=startRowU[pivotRow];
    nInRow=numberInRowU[pivotRow];
    end= start + nInRow;
    CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1];
    CoinSimplexInt *  COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    if (nInRow<10) {
      CoinSimplexInt smallest=numberRowsExtra_;
      for (CoinBigIndex i = start; i < end ; i ++ ) {
	CoinSimplexInt jColumn = indexColumnU[i];
	if (pivotRowForward[jColumn]<smallest) {
	  smallest=pivotRowForward[jColumn];
	  smallestIndex=jColumn;
	}
#ifndef ABC_USE_FUNCTION_POINTERS
#ifdef CONVERTDEBUG
	CoinBigIndex j = convertRowToColumn[i]+startColumnU[jColumn];
	assert (fabs(elementU[j]-elementRowU[i])<1.0e-4);
#endif      
	region[jColumn] = elementRowU[i];
#else
#ifdef CONVERTDEBUG
	CoinBigIndex j = convertRowToColumn[i];
	CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter[jColumn].offset;
	assert (fabs(area[j]-elementRowU[i])<1.0e-4);
#endif      
	region[jColumn] = elementRowU[i];
#endif
	regionIndex[numberNonZero++] = jColumn;
      }
    } else {
      for (CoinBigIndex i = start; i < end ; i ++ ) {
	CoinSimplexInt jColumn = indexColumnU[i];
#ifdef CONVERTDEBUG
#ifdef ABC_USE_FUNCTION_POINTERS
	CoinBigIndex j = convertRowToColumn[i];
	CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter[jColumn].offset;
	assert (fabs(area[j]-elementRowU[i])<1.0e-4);
#else
	CoinBigIndex j = convertRowToColumn[i]+startColumnU[jColumn];
	assert (fabs(elementU[j]-elementRowU[i])<1.0e-4);
#endif
#endif      
	region[jColumn] = elementRowU[i];
	regionIndex[numberNonZero++] = jColumn;
      }
    }
    //do BTRAN - finding first one to use
    regionSparse->setNumElements ( numberNonZero );
    if (numberNonZero) {
      assert (smallestIndex>=0);
#ifndef NDEBUG
      const CoinSimplexInt *  COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
      CoinSimplexInt jRow=pivotLinked[-1];
      if (jRow!=smallestIndex) {
	while (jRow>=0) {
	  CoinFactorizationDouble pivotValue = region[jRow];
	  if (pivotValue)
	    break;
	  jRow=pivotLinked[jRow];
	}
	assert (jRow==smallestIndex);
      }
#endif
      //smallestIndex=pivotLinkedForwardsAddress_[-1];
      updateColumnTransposeU ( regionSparse, smallestIndex
#if ABC_SMALL < 2
		  ,reinterpret_cast<CoinAbcStatistics &>(btranCountInput_)
#endif
#if ABC_PARALLEL
		    ,0
#endif
);
    }
  } else {
#endif
#if ABC_SMALL >= 0
    // No row copy check space
    CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_;
    CoinFactorizationDouble *  COIN_RESTRICT elementR = elementRAddress_;
    CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast<CoinBigIndex *>(elementR+lengthR_);
    CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast<CoinSimplexInt *>(indexRowR+lengthR_);
    nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow);
#endif
#if ABC_SMALL < 2
  }
#endif
  numberNonZero = regionSparse->getNumElements (  );
  //printf("replace nels %d\n",numberNonZero);
  CoinFactorizationDouble saveFromU = 0.0;

  for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) {
    CoinSimplexInt iRow = indexU2[i];
    if ( iRow != pivotRow ) {
      saveFromU -= elementU2[i] * region[iRow];
    } else {
      saveFromU += elementU2[i];
    }
  }       
  //check accuracy
  status = checkPivot(saveFromU,pivotCheck);
  if (status==1&&!numberPivots_) {
    printf("check status ok\n");
    status=2;
  }
  pivotCheck=saveFromU;
  return status;
}
//  replaceColumn.  Replaces one Column to basis
//      returns 0=OK, 1=Probably OK, 2=singular, 3=no room
//partial update already in U
CoinSimplexInt
CoinAbcTypeFactorization::replaceColumn ( CoinIndexedVector * regionSparse,
                                 CoinSimplexInt pivotRow,
				  CoinSimplexDouble pivotCheck ,
				  bool skipBtranU,
				   CoinSimplexDouble )
{
  assert (numberU_<=numberRowsExtra_);

#ifndef ALWAYS_SKIP_BTRAN
  //return at once if too many iterations
  if ( numberRowsExtra_ >= maximumRowsExtra_ ) {
    return 5;
  }       
  if ( lengthAreaU_ < lastEntryByColumnU_ ) {
    return 3;
  }
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_;
#endif
  CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_;
#if ABC_SMALL < 2
  CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
#if ABC_SMALL < 2
  CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
#endif
  CoinSimplexInt *  COIN_RESTRICT permuteLookup = pivotColumnAddress_;
  CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse);
  
  //take out old pivot column

#ifndef ABC_USE_FUNCTION_POINTERS
  totalElements_ -= numberInColumn[pivotRow];
#else
  scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
  extern scatterUpdate AbcScatterLowSubtract[9];
  extern scatterUpdate AbcScatterHighSubtract[4];
  CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
  totalElements_ -= scatter[pivotRow].number;
  CoinBigIndex saveStart = scatter[pivotRow].offset;
  CoinBigIndex saveEnd = scatter[pivotRow].number;
  scatter[pivotRow].offset=startU;
  CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
  CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU;
  CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast<CoinSimplexInt *>(elementU2+numberInColumnU2);
#endif
#ifndef ALWAYS_SKIP_BTRAN

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex saveStart = startColumnU[pivotRow];
  CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow];
#endif
#endif
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
  CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#if CONVERTROW > 2
  CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices (  );
  CoinFactorizationDouble pivotValue = 1.0;
  CoinSimplexInt status=0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *  COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif
  CoinFactorizationDouble *  COIN_RESTRICT elementR = elementRAddress_;

#ifndef NDEBUG
#if CONVERTROW
#define CONVERTDEBUG
#endif
#endif
  int nInRow;
#if ABC_SMALL < 2
  CoinBigIndex start=0;
  CoinBigIndex end=0;
  if (gotUCopy()) {
    start=startRowU[pivotRow];
    nInRow=numberInRowU[pivotRow];
    end= start + nInRow;
  }
#endif
  CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_;
#ifndef ALWAYS_SKIP_BTRAN
  if (!skipBtranU) {
  CoinFactorizationDouble oldPivot = pivotRegion[pivotRow];
  // for accuracy check
  pivotCheck = pivotCheck / oldPivot;
#if ABC_SMALL < 2
  if (gotUCopy()) {
    CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1];
    CoinSimplexInt *  COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    if (nInRow<10) {
      CoinSimplexInt smallest=numberRowsExtra_;
      for (CoinBigIndex i = start; i < end ; i ++ ) {
	CoinSimplexInt jColumn = indexColumnU[i];
	if (pivotRowForward[jColumn]<smallest) {
	  smallest=pivotRowForward[jColumn];
	  smallestIndex=jColumn;
	}
#ifndef ABC_USE_FUNCTION_POINTERS
#ifdef CONVERTDEBUG
	CoinBigIndex j = convertRowToColumn[i]+startColumnU[jColumn];
	assert (fabs(elementU[j]-elementRowU[i])<1.0e-4);
#endif      
	region[jColumn] = elementRowU[i];
#else
#ifdef CONVERTDEBUG
	CoinBigIndex j = convertRowToColumn[i];
	CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter[jColumn].offset;
	assert (fabs(area[j]-elementRowU[i])<1.0e-4);
#endif      
	region[jColumn] = elementRowU[i];
#endif
	regionIndex[numberNonZero++] = jColumn;
      }
    } else {
      for (CoinBigIndex i = start; i < end ; i ++ ) {
	CoinSimplexInt jColumn = indexColumnU[i];
#ifdef CONVERTDEBUG
#ifdef ABC_USE_FUNCTION_POINTERS
	CoinBigIndex j = convertRowToColumn[i];
	CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter[jColumn].offset;
	assert (fabs(area[j]-elementRowU[i])<1.0e-4);
#else
	CoinBigIndex j = convertRowToColumn[i]+startColumnU[jColumn];
	assert (fabs(elementU[j]-elementRowU[i])<1.0e-4);
#endif
#endif      
	region[jColumn] = elementRowU[i];
	regionIndex[numberNonZero++] = jColumn;
      }
    }
    //do BTRAN - finding first one to use
    regionSparse->setNumElements ( numberNonZero );
    if (numberNonZero) {
      assert (smallestIndex>=0);
#ifndef NDEBUG
      const CoinSimplexInt *  COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
      CoinSimplexInt jRow=pivotLinked[-1];
      if (jRow!=smallestIndex) {
	while (jRow>=0) {
	  CoinFactorizationDouble pivotValue = region[jRow];
	  if (pivotValue)
	    break;
	  jRow=pivotLinked[jRow];
	}
	assert (jRow==smallestIndex);
      }
#endif
      //smallestIndex=pivotLinkedForwardsAddress_[-1];
      updateColumnTransposeU ( regionSparse, smallestIndex
#if ABC_SMALL < 2
		  ,reinterpret_cast<CoinAbcStatistics &>(btranCountInput_)
#endif
#if ABC_PARALLEL
		    ,0
#endif
);
    }
  } else {
#endif
#if ABC_SMALL >= 0
    // No row copy check space
    if ( lengthR_ + numberRows_>= lengthAreaR_ ) {
      //not enough room
      return 3;
    }       
    CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast<CoinBigIndex *>(elementR+lengthR_);
    CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast<CoinSimplexInt *>(indexRowR+lengthR_);
    nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow);
#endif
#if ABC_SMALL < 2
  }
#endif
  }
#endif
  numberNonZero = regionSparse->getNumElements (  );
  CoinFactorizationDouble saveFromU = 0.0;

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex startU = startColumnU[numberRows_];
  startColumnU[pivotRow]=startU;
  CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_];
#else
//CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
#endif
  instrument_do("CoinAbcFactorizationReplaceColumn",2*numberRows_+4*numberInColumnU2);
#ifndef ALWAYS_SKIP_BTRAN
  if (!skipBtranU) {
  for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) {
    CoinSimplexInt iRow = indexU2[i];
    if ( iRow != pivotRow ) {
      saveFromU -= elementU2[i] * region[iRow];
    } else {
      saveFromU += elementU2[i];
    }
  }       
  //check accuracy
  status = checkPivot(saveFromU,pivotCheck);
  } else {
    status=0;
    saveFromU=pivotCheck;
  }
  //regionSparse->print();
#endif
  if (status>1||(status==1&&!numberPivots_)) {
    // restore some things
    //pivotRegion[pivotRow] = oldPivot;
    CoinSimplexInt number = saveEnd-saveStart;
    totalElements_ += number;
    //numberInColumn[pivotRow]=number;
    regionSparse->clear();
    return status;
  } else {
    pivotValue = 1.0 / saveFromU;
    // do what we would have done by now
#if ABC_SMALL < 2
    if (gotUCopy()) {
      for (CoinBigIndex i = start; i < end ; i ++ ) {
	CoinSimplexInt jColumn = indexColumnU[i];
#ifndef ABC_USE_FUNCTION_POINTERS
	CoinBigIndex startColumn = startColumnU[jColumn];
#if CONVERTROW
	CoinBigIndex j = convertRowToColumn[i];
#else
	CoinBigIndex j;
	int number = numberInColumn[jColumn];
	for (j=0;j<number;j++) {
	  if (indexRowU[j+startColumn]==pivotRow)
	    break;
	}
	assert (j<number);
	//assert (j==convertRowToColumn[i]); // temp
#endif
#ifdef CONVERTDEBUG
	assert (fabs(elementU[j+startColumn]-elementRowU[i])<1.0e-4);
#endif
#else
	int number = scatter[jColumn].number;
	CoinSimplexInt k = number-1;
	scatter[jColumn].number=k;
	CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+scatter[jColumn].offset;
	CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+k+1);
#if CONVERTROW
	CoinSimplexInt j = convertRowToColumn[i];
#else
	CoinSimplexInt j;
	for (j=0;j<number;j++) {
	  if (indices[j]==pivotRow)
	    break;
	}
	assert (j<number);
	//assert (j==convertRowToColumn[i]); // temp
#endif
#ifdef CONVERTDEBUG
	assert (fabs(area[j]-elementRowU[i])<1.0e-4);
#endif
#endif
	// swap
#ifndef ABC_USE_FUNCTION_POINTERS
	CoinSimplexInt k = numberInColumn[jColumn]-1;
	numberInColumn[jColumn]=k;
	CoinBigIndex k2 = k+startColumn;
	int kRow2=indexRowU[k2];
	indexRowU[j+startColumn]=kRow2;
	CoinFactorizationDouble value2=elementU[k2];
	elementU[j+startColumn]=value2;
#else
	int kRow2=indices[k];
	CoinFactorizationDouble value2=area[k];
#if ABC_USE_FUNCTION_POINTERS
	if (k<9) {
	  scatter[jColumn].functionPointer=AbcScatterLowSubtract[k];
	} else {
	  scatter[jColumn].functionPointer=AbcScatterHighSubtract[k&3];
	}
#endif
	// later more complicated swap to avoid move
	indices[j]=kRow2;
	area[j]=value2;
	// move 
	indices-=2;
	for (int i=0;i<k;i++)
	  indices[i]=indices[i+2];
#endif
	// move in row copy (slow - as other remark (but shouldn't need to))
	CoinBigIndex start2 = startRowU[kRow2];
	int n=numberInRowU[kRow2];
	CoinBigIndex end2 = start2 + n;
#ifndef NDEBUG
	bool found=false;
#endif
	for (CoinBigIndex i2 = start2; i2 < end2 ; i2 ++ ) {
	  CoinSimplexInt iColumn2 = indexColumnU[i2];
	  if (jColumn==iColumn2) {
#if CONVERTROW
	    convertRowToColumn[i2] = j;
#endif
#ifndef NDEBUG
	    found=true;
#endif
	    break;
	  }
	}
#ifndef NDEBUG
	assert(found);
#endif
      }
    } else {
#endif
#if ABC_SMALL >= 0
      // no row copy
      CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast<CoinBigIndex *>(elementR+lengthR_);
      CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast<CoinSimplexInt *>(indexRowR+lengthR_);
      for (CoinSimplexInt i = 0; i < nInRow ; i ++ ) {
	CoinBigIndex j = deletedPosition[i];
	CoinSimplexInt jColumn = deletedColumns[i];
	// swap
	CoinSimplexInt k = numberInColumn[jColumn]-1;
	numberInColumn[jColumn]=k;
	CoinBigIndex k2 = k+startColumnU[jColumn];
	int kRow2=indexRowU[k2];
	indexRowU[j]=kRow2;
	CoinFactorizationDouble value2=elementU[k2];
	elementU[j]=value2;
      }
#endif
#if ABC_SMALL < 2
    }
#endif
  }
#if ABC_SMALL < 2
  if (gotUCopy()) {
    // Now zero out column of U
    //take out old pivot column
#ifdef ABC_USE_FUNCTION_POINTERS
    CoinFactorizationDouble * COIN_RESTRICT elementU = elementUColumnPlus+saveStart;
    saveStart=0;
    CoinSimplexInt * COIN_RESTRICT indexRowU = reinterpret_cast<CoinSimplexInt *>(elementU+saveEnd);
#endif
    for (CoinBigIndex i = saveStart; i < saveEnd ; i ++ ) {
      //elementU[i] = 0.0;
      // If too slow then reverse meaning of convertRowToColumn and use
      int jRow=indexRowU[i];
      CoinBigIndex start = startRowU[jRow];
      CoinBigIndex end = start + numberInRowU[jRow];
      for (CoinBigIndex j = start; j < end ; j ++ ) {
	CoinSimplexInt jColumn = indexColumnU[j];
	if (jColumn==pivotRow) {
	  // swap
	  numberInRowU[jRow]--;
	  elementRowU[j]=elementRowU[end-1];
#if CONVERTROW
	  convertRowToColumn[j]=convertRowToColumn[end-1];
#endif
	  indexColumnU[j]=indexColumnU[end-1];
	  break;
	}
      }
    }    
  }
#endif   
  //zero out pivot Row (before or after?)
  //add to R
  CoinBigIndex * COIN_RESTRICT startColumnR = startColumnRAddress_;
  CoinBigIndex putR = lengthR_;
  CoinSimplexInt number = numberR_;
  
  startColumnR[number] = putR;  //for luck and first time
  number++;
  //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2));
  startColumnR[number] = putR + numberNonZero;
  numberR_ = number;
  lengthR_ = putR + numberNonZero;
  totalElements_ += numberNonZero;
  if ( lengthR_ >= lengthAreaR_ ) {
    //not enough room
    regionSparse->clear();
    return 3;
  }       
  if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) {
    //not enough room
    regionSparse->clear();
    return 3;
  }

#if ABC_SMALL < 2
  CoinSimplexInt *  COIN_RESTRICT nextRow=NULL;
  CoinSimplexInt *  COIN_RESTRICT lastRow=NULL;
  CoinSimplexInt next;
  CoinSimplexInt last;
  if (gotUCopy()) {
    //take out row
    nextRow = nextRowAddress_;
    lastRow = lastRowAddress_;
    next = nextRow[pivotRow];
    last = lastRow[pivotRow];
    
    nextRow[last] = next;
    lastRow[next] = last;
    numberInRowU[pivotRow]=0;
  }
#endif  
  //put in pivot
  //add row counts
  
  int n = 0;
  for (CoinSimplexInt i = 0; i < numberInColumnU2; i++ ) {
    CoinSimplexInt iRow = indexU2[i];
    CoinFactorizationDouble value=elementU2[i];
    assert (value);
    if ( !TEST_LESS_THAN_TOLERANCE(value ) ) {
      if ( iRow != pivotRow ) {
	//modify by pivot
	CoinFactorizationDouble value2 = value*pivotValue;
	indexU2[n]=iRow;
	elementU2[n++] = value2;
#if ABC_SMALL < 2
	if (gotUCopy()) {
	  CoinSimplexInt next = nextRow[iRow];
	  CoinSimplexInt iNumberInRow = numberInRowU[iRow];
	  CoinBigIndex space;
	  CoinBigIndex put = startRowU[iRow] + iNumberInRow;
	  space = startRowU[next] - put;
	  if ( space <= 0 ) {
	    getRowSpaceIterate ( iRow, iNumberInRow + 4 );
	    put = startRowU[iRow] + iNumberInRow;
	  } else if (next==numberRows_) {
	    lastEntryByRowU_=put+1;
	  }     
	  indexColumnU[put] = pivotRow;
#if CONVERTROW
	  convertRowToColumn[put] = i;
#endif
	  elementRowU[put] = value2;
	  numberInRowU[iRow] = iNumberInRow + 1;
	}
#endif
      } else {
	//swap and save
	indexU2[i]=indexU2[numberInColumnU2-1];
	elementU2[i] = elementU2[numberInColumnU2-1];
	numberInColumnU2--;
	i--;
      }
    } else {
      // swap
      indexU2[i]=indexU2[numberInColumnU2-1];
      elementU2[i] = elementU2[numberInColumnU2-1];
      numberInColumnU2--;
      i--;
    }       
  }       
  numberInColumnU2=n;
  //do permute
  permuteAddress_[numberRowsExtra_] = pivotRow;
  //and for safety
  permuteAddress_[numberRowsExtra_ + 1] = 0;

  //pivotColumnAddress_[pivotRow] = numberRowsExtra_;
  
  numberU_++;

#if ABC_SMALL < 2
  if (gotUCopy()) {
    //in at end
    last = lastRow[numberRows_];
    nextRow[last] = pivotRow; //numberRowsExtra_;
    lastRow[numberRows_] = pivotRow; //numberRowsExtra_;
    lastRow[pivotRow] = last;
    nextRow[pivotRow] = numberRows_;
    startRowU[pivotRow] = lastEntryByRowU_;
  }
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  numberInColumn[pivotRow]=numberInColumnU2;
#else
#if ABC_USE_FUNCTION_POINTERS
  if (numberInColumnU2<9) {
    scatter[pivotRow].functionPointer=AbcScatterLowSubtract[numberInColumnU2];
  } else {
    scatter[pivotRow].functionPointer=AbcScatterHighSubtract[numberInColumnU2&3];
  }
#endif
  assert(scatter[pivotRow].offset==lastEntryByColumnUPlus_);
  //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_;
  //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+numberInColumnU2);
  if (numberInColumnU2<scatter[numberRows_].number) {
    int offset=2*(scatter[numberRows_].number-numberInColumnU2);
    indexU2 -= offset;
    //assert(indexU2-reinterpret_cast<int*>(area)>=0);
    for (int i=0;i<numberInColumnU2;i++)
      indexU2[i]=indexU2[i+offset];
  }
  scatter[pivotRow].number=numberInColumnU2;
  //CoinAbcMemcpy(indices,indexU2,numberInColumnU2);
  //CoinAbcMemcpy(area,elementU2,numberInColumnU2);
  lastEntryByColumnUPlus_ += (3*numberInColumnU2+1)>>1;
#endif
  totalElements_ += numberInColumnU2;
  lengthU_ += numberInColumnU2;
#if ABC_SMALL < 2
  CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_;
  if (gotRCopy()) {
    //column in at beginning (as empty)
    next = nextColumn[maximumRowsExtra_];
    lastColumn[next] = numberRowsExtra_;
    nextColumn[maximumRowsExtra_] = numberRowsExtra_;
    nextColumn[numberRowsExtra_] = next;
    lastColumn[numberRowsExtra_] = maximumRowsExtra_;
  }
#endif
#if 0
  {
    int k=-1;
    for (int i=0;i<numberRows_;i++) {
      k=CoinMax(k,startRowU[i]+numberInRowU[i]);
    }
    assert (k==lastEntryByRowU_);
  }
#endif
  //pivotRegion[numberRowsExtra_] = pivotValue;
  pivotRegion[pivotRow] = pivotValue;
#ifndef ABC_USE_FUNCTION_POINTERS
  maximumU_ = CoinMax(maximumU_,startU+numberInColumnU2);
#else
  maximumU_ = CoinMax(maximumU_,lastEntryByColumnUPlus_);
#endif
  permuteLookup[pivotRow]=numberRowsExtra_;
  permuteLookup[numberRowsExtra_]=pivotRow;
  //pivotColumnAddress_[pivotRow]=numberRowsExtra_;
  //pivotColumnAddress_[numberRowsExtra_]=pivotRow;
  assert (pivotRow<numberRows_);
  // out of chain
  CoinSimplexInt iLast=pivotLinkedBackwardsAddress_[pivotRow];
  CoinSimplexInt iNext=pivotLinkedForwardsAddress_[pivotRow];
  assert (pivotRow==pivotLinkedForwardsAddress_[iLast]);
  assert (pivotRow==pivotLinkedBackwardsAddress_[iNext]);
  pivotLinkedForwardsAddress_[iLast]=iNext;
  pivotLinkedBackwardsAddress_[iNext]=iLast;
  if (pivotRow==lastSlack_) {
    lastSlack_ = iLast;
  }
  iLast=pivotLinkedBackwardsAddress_[numberRows_];
  assert (numberRows_==pivotLinkedForwardsAddress_[iLast]);
  pivotLinkedForwardsAddress_[iLast]=pivotRow;
  pivotLinkedBackwardsAddress_[pivotRow]=iLast;
  pivotLinkedBackwardsAddress_[numberRows_]=pivotRow;
  pivotLinkedForwardsAddress_[pivotRow]=numberRows_;
  assert (numberRows_>pivotLinkedForwardsAddress_[-1]);
  assert (pivotLinkedBackwardsAddress_[numberRows_]>=0);
  numberRowsExtra_++;
  numberGoodU_++;
  numberPivots_++;
  if ( numberRowsExtra_ > numberRows_ + 50 ) {
    CoinBigIndex extra = factorElements_ >> 1;
    
    if ( numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500 ) {
      if ( extra < 2 * numberRows_ ) {
        extra = 2 * numberRows_;
      }       
    } else {
      if ( extra < 5 * numberRows_ ) {
        extra = 5 * numberRows_;
      }       
    }       
    CoinBigIndex added = totalElements_ - factorElements_;
    
    if ( added > extra && added > ( factorElements_ ) << 1 && !status 
	 && 3*totalElements_ > 2*(lengthAreaU_+lengthAreaL_)) {
      status = 3;
      if ( messageLevel_ & 4 ) {
        std::cout << "Factorization has "<< totalElements_
		  << ", basis had " << factorElements_ <<std::endl;
      }
    }       
  }
#if ABC_SMALL < 2
  if (gotRCopy()&&status<2) {
    //if (numberInColumnPlus&&status<2) {
    // we are going to put another copy of R in R
    CoinFactorizationDouble * COIN_RESTRICT elementRR = elementRAddress_ + lengthAreaR_;
    CoinSimplexInt * COIN_RESTRICT indexRowRR = indexRowRAddress_ + lengthAreaR_;
    CoinBigIndex * COIN_RESTRICT startRR = startColumnRAddress_+maximumPivots_+1;
    CoinSimplexInt pivotRow = numberRowsExtra_-1;
    for (CoinBigIndex i = 0; i < numberNonZero; i++ ) {
      CoinSimplexInt jRow = regionIndex[i];
      CoinFactorizationDouble value=region[jRow];
      elementR[putR] = value;
      indexRowR[putR] = jRow;
      putR++;
      region[jRow]=0.0;
      int iRow = permuteLookup[jRow];
      next = nextColumn[iRow];
      CoinBigIndex space;
      if (next!=maximumRowsExtra_)
	space = startRR[next]-startRR[iRow];
      else
	space = lengthAreaR_-startRR[iRow];
      CoinSimplexInt numberInR = numberInColumnPlus[iRow];
      if (space>numberInR) {
	// there is space
	CoinBigIndex  put=startRR[iRow]+numberInR;
	numberInColumnPlus[iRow]=numberInR+1;
	indexRowRR[put]=pivotRow;
	elementRR[put]=value;
	//add 4 for luck
	if (next==maximumRowsExtra_)
	  startRR[maximumRowsExtra_] = CoinMin(static_cast<CoinBigIndex> (put + 4) ,lengthAreaR_);
      } else {
	// no space - do we shuffle?
	if (!getColumnSpaceIterateR(iRow,value,pivotRow)) {
	  // printf("Need more space for R\n");
	  numberInColumnPlus_.conditionalDelete();
	  numberInColumnPlusAddress_=NULL;
	  setNoGotRCopy();
	  regionSparse->clear();
#if ABC_SMALL < 0
	  status=3;
#endif
	  break;
	}
      }
    }       
  } else {
#endif
    for (CoinBigIndex i = 0; i < numberNonZero; i++ ) {
      CoinSimplexInt iRow = regionIndex[i];
      elementR[putR] = region[iRow];
      region[iRow]=0.0;
      indexRowR[putR] = iRow;
      putR++;
    }
#if ABC_SMALL < 2
  }
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
#if 0
  {
    CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
    extern scatterUpdate AbcScatterLowSubtract[9];
    extern scatterUpdate AbcScatterHighSubtract[4];
    printf("=============================================start\n");
    for (int iRow=0;iRow<numberRows_;iRow++) {
      int number=scatter[iRow].number;
      CoinBigIndex offset = scatter[iRow].offset;
      CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+offset;
      CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+number);
      CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow];
      CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow];
      //assert (number==numberInColumn[iRow]);
#if ABC_USE_FUNCTION_POINTERS
      if (number<9)
	assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]);
      else
	assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]);
#endif
      if (number)
	printf("Row %d %d els\n",iRow,number);
      int n=0;
      for (int i=0;i<number;i++) {
	printf("(%d,%g) ",indices[i],area[i]);
	n++;
	if (n==10) {
	  n=0;
	  printf("\n");
	}
      }
      if (n)
	printf("\n");
#if 0
      for (int i=0;i<number;i++) {
	assert (indices[i]==indices2[i]);
	assert (area[i]==area2[i]);
      }
#endif
    }
    printf("=============================================end\n");
  }
#endif
#endif
  regionSparse->setNumElements(0);
  //for (int i=0;i<numberRows_;i++) 
  //assert(permuteLookupAddress_[i]==pivotColumnAddress_[i]);
  return status;
}
#endif
/* Checks if can replace one Column to basis,
   returns update alpha
   Fills in region for use later
   partial update already in U */
#ifdef ABC_LONG_FACTORIZATION
long
#endif
  double
  CoinAbcTypeFactorization::checkReplacePart1(CoinIndexedVector *regionSparse,
    int pivotRow)
{
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
  CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU;
  //CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast<CoinSimplexInt *>(elementU2+numberInColumnU2);
#else
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinBigIndex startU = startColumnU[numberRows_];
  CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_];
#endif
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
  //zeroed out region
  toLongArray(regionSparse, 3);
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_;

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex saveStart = startColumnU[pivotRow];
  CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow];
#endif
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
#ifndef NDEBUG
#define CONVERTDEBUG
#endif
#ifdef CONVERTDEBUG
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#endif
#if CONVERTROW > 2
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  //CoinSimplexInt status=0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif

  int nInRow;
#if ABC_SMALL < 2
  CoinBigIndex start = 0;
  CoinBigIndex end = 0;
  if (gotUCopy()) {
    start = startRowU[pivotRow];
    nInRow = numberInRowU[pivotRow];
    end = start + nInRow;
    CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1];
    CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    if (nInRow < 10) {
      CoinSimplexInt smallest = numberRowsExtra_;
      for (CoinBigIndex i = start; i < end; i++) {
        CoinSimplexInt jColumn = indexColumnU[i];
        if (pivotRowForward[jColumn] < smallest) {
          smallest = pivotRowForward[jColumn];
          smallestIndex = jColumn;
        }
#ifndef ABC_USE_FUNCTION_POINTERS
#ifdef CONVERTDEBUG
        CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn];
        assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4);
#endif
        region[jColumn] = elementRowU[i];
#else
#ifdef CONVERTDEBUG
        CoinBigIndex j = convertRowToColumn[i];
        CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
        assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#endif
        region[jColumn] = elementRowU[i];
#endif
        regionIndex[numberNonZero++] = jColumn;
      }
    } else {
      for (CoinBigIndex i = start; i < end; i++) {
        CoinSimplexInt jColumn = indexColumnU[i];
#ifdef CONVERTDEBUG
#ifdef ABC_USE_FUNCTION_POINTERS
        CoinBigIndex j = convertRowToColumn[i];
        CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
        assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#else
        CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn];
        assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4);
#endif
#endif
        region[jColumn] = elementRowU[i];
        regionIndex[numberNonZero++] = jColumn;
      }
    }
    //do BTRAN - finding first one to use
    regionSparse->setNumElements(numberNonZero);
    if (numberNonZero) {
      assert(smallestIndex >= 0);
#ifndef NDEBUG
      const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
      CoinSimplexInt jRow = pivotLinked[-1];
      if (jRow != smallestIndex) {
        while (jRow >= 0) {
          CoinFactorizationDouble pivotValue = region[jRow];
          if (pivotValue)
            break;
          jRow = pivotLinked[jRow];
        }
        assert(jRow == smallestIndex);
      }
#endif
#if ABC_PARALLEL == 0
      //smallestIndex=pivotLinkedForwardsAddress_[-1];
      updateColumnTransposeU(regionSparse, smallestIndex
#if ABC_SMALL < 2
        ,
        reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
      );
#else
      assert(FACTOR_CPU > 3);
      updateColumnTransposeU(regionSparse, smallestIndex
#if ABC_SMALL < 2
        ,
        reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
          ,
        3);
#endif
    }
  } else {
#endif
#if ABC_SMALL >= 0
    // No row copy check space
    CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_;
    CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_);
    CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_);
    nInRow = replaceColumnU(regionSparse, deletedPosition, deletedColumns, pivotRow);
#endif
#if ABC_SMALL < 2
  }
#endif
  if (lengthR_ + numberRows_ >= lengthAreaR_) {
    //not enough room
    return 0.0;
  }
#ifdef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2);
#endif
  if (lengthU_ + numberInColumnU2 >= lengthAreaU_) {
    //not enough room
    return 0.0;
  }
  //CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector (  );
  //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices (  );
  //CoinSimplexInt status=0;

  //int numberNonZero = regionSparse->getNumElements (  );
  //printf("replace nels %d\n",numberNonZero);
  CoinFactorizationDouble saveFromU = 0.0;

  for (CoinBigIndex i = 0; i < numberInColumnU2; i++) {
    CoinSimplexInt iRow = indexU2[i];
    if (iRow != pivotRow) {
      saveFromU -= elementU2[i] * region[iRow];
    } else {
      saveFromU += elementU2[i];
    }
  }
  return saveFromU;
}
/* Checks if can replace one Column to basis,
   returns update alpha
   Fills in region for use later
   partial update in vector */
#ifdef ABC_LONG_FACTORIZATION
long
#endif
  double
  CoinAbcTypeFactorization::checkReplacePart1(CoinIndexedVector *regionSparse,
    CoinIndexedVector *partialUpdate,
    int pivotRow)
{
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
#else
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT indexU2 = partialUpdate->getIndices();
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = denseVector(partialUpdate);
  CoinSimplexInt numberInColumnU2 = partialUpdate->getNumElements();
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
  //zeroed out region
  toLongArray(regionSparse, 3);
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_;

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex saveStart = startColumnU[pivotRow];
  CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow];
#endif
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
#ifndef NDEBUG
#define CONVERTDEBUG
#endif
#ifdef CONVERTDEBUG
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#endif
#if CONVERTROW > 2
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  //CoinSimplexInt status=0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif

  int nInRow;
#if ABC_SMALL < 2
  CoinBigIndex start = 0;
  CoinBigIndex end = 0;
  if (gotUCopy()) {
    start = startRowU[pivotRow];
    nInRow = numberInRowU[pivotRow];
    end = start + nInRow;
    CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1];
    CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    if (nInRow < 10) {
      CoinSimplexInt smallest = numberRowsExtra_;
      for (CoinBigIndex i = start; i < end; i++) {
        CoinSimplexInt jColumn = indexColumnU[i];
        if (pivotRowForward[jColumn] < smallest) {
          smallest = pivotRowForward[jColumn];
          smallestIndex = jColumn;
        }
#ifndef ABC_USE_FUNCTION_POINTERS
#ifdef CONVERTDEBUG
        CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn];
        assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4);
#endif
        region[jColumn] = elementRowU[i];
#else
#ifdef CONVERTDEBUG
        CoinBigIndex j = convertRowToColumn[i];
        CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
        assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#endif
        region[jColumn] = elementRowU[i];
#endif
        regionIndex[numberNonZero++] = jColumn;
      }
    } else {
      for (CoinBigIndex i = start; i < end; i++) {
        CoinSimplexInt jColumn = indexColumnU[i];
#ifdef CONVERTDEBUG
#ifdef ABC_USE_FUNCTION_POINTERS
        CoinBigIndex j = convertRowToColumn[i];
        CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
        assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#else
        CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn];
        assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4);
#endif
#endif
        region[jColumn] = elementRowU[i];
        regionIndex[numberNonZero++] = jColumn;
      }
    }
    //do BTRAN - finding first one to use
    regionSparse->setNumElements(numberNonZero);
    if (numberNonZero) {
      assert(smallestIndex >= 0);
#ifndef NDEBUG
      const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
      CoinSimplexInt jRow = pivotLinked[-1];
      if (jRow != smallestIndex) {
        while (jRow >= 0) {
          CoinFactorizationDouble pivotValue = region[jRow];
          if (pivotValue)
            break;
          jRow = pivotLinked[jRow];
        }
        assert(jRow == smallestIndex);
      }
#endif
#if ABC_PARALLEL == 0
      //smallestIndex=pivotLinkedForwardsAddress_[-1];
      updateColumnTransposeU(regionSparse, smallestIndex
#if ABC_SMALL < 2
        ,
        reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
      );
#else
      assert(FACTOR_CPU > 3);
      updateColumnTransposeU(regionSparse, smallestIndex
#if ABC_SMALL < 2
        ,
        reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
          ,
        3);
#endif
    }
  } else {
#endif
#if ABC_SMALL >= 0
    // No row copy check space
    CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_;
    CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_);
    CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_);
    nInRow = replaceColumnU(regionSparse, deletedPosition, deletedColumns, pivotRow);
#endif
#if ABC_SMALL < 2
  }
#endif
  if (lengthR_ + numberRows_ >= lengthAreaR_) {
    //not enough room
    return 0.0;
  }
  if (lengthU_ + numberInColumnU2 >= lengthAreaU_) {
    //not enough room
    partialUpdate->clear();
    return 0.0;
  }
  //CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector (  );
  //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices (  );
  //CoinSimplexInt status=0;

  //int numberNonZero = regionSparse->getNumElements (  );
  //printf("replace nels %d\n",numberNonZero);
  CoinFactorizationDouble saveFromU = 0.0;

  for (CoinBigIndex i = 0; i < numberInColumnU2; i++) {
    CoinSimplexInt iRow = indexU2[i];
    if (iRow != pivotRow) {
      saveFromU -= elementU2[iRow] * region[iRow];
    } else {
      saveFromU += elementU2[iRow];
    }
  }
  return saveFromU;
}
#ifdef MOVE_REPLACE_PART1A
/* Checks if can replace one Column in basis,
   returns update alpha
   Fills in region for use later
   partial update already in U */
void CoinAbcTypeFactorization::checkReplacePart1a(CoinIndexedVector *regionSparse,
  int pivotRow)
{
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
  CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU;
  //CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast<CoinSimplexInt *>(elementU2+numberInColumnU2);
#else
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinBigIndex startU = startColumnU[numberRows_];
  CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_];
#endif
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
  //zeroed out region
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_;

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex saveStart = startColumnU[pivotRow];
  CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow];
#endif
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
#ifndef NDEBUG
#define CONVERTDEBUG
#endif
#ifdef CONVERTDEBUG
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#endif
#if CONVERTROW > 2
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  //CoinSimplexInt status=0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif

  int nInRow;
#if ABC_SMALL < 2
  CoinBigIndex start = 0;
  CoinBigIndex end = 0;
  if (gotUCopy()) {
    start = startRowU[pivotRow];
    nInRow = numberInRowU[pivotRow];
    end = start + nInRow;
    CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1];
    CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    if (nInRow < 10) {
      CoinSimplexInt smallest = numberRowsExtra_;
      for (CoinBigIndex i = start; i < end; i++) {
        CoinSimplexInt jColumn = indexColumnU[i];
        if (pivotRowForward[jColumn] < smallest) {
          smallest = pivotRowForward[jColumn];
          smallestIndex = jColumn;
        }
#ifndef ABC_USE_FUNCTION_POINTERS
#ifdef CONVERTDEBUG
        CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn];
        assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4);
#endif
        region[jColumn] = elementRowU[i];
#else
#ifdef CONVERTDEBUG
        CoinBigIndex j = convertRowToColumn[i];
        CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
        assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#endif
        region[jColumn] = elementRowU[i];
#endif
        regionIndex[numberNonZero++] = jColumn;
      }
    } else {
      for (CoinBigIndex i = start; i < end; i++) {
        CoinSimplexInt jColumn = indexColumnU[i];
#ifdef CONVERTDEBUG
#ifdef ABC_USE_FUNCTION_POINTERS
        CoinBigIndex j = convertRowToColumn[i];
        CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
        assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#else
        CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn];
        assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4);
#endif
#endif
        region[jColumn] = elementRowU[i];
        regionIndex[numberNonZero++] = jColumn;
      }
    }
    //do BTRAN - finding first one to use
    regionSparse->setNumElements(numberNonZero);
    if (numberNonZero) {
      assert(smallestIndex >= 0);
#ifndef NDEBUG
      const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
      CoinSimplexInt jRow = pivotLinked[-1];
      if (jRow != smallestIndex) {
        while (jRow >= 0) {
          CoinFactorizationDouble pivotValue = region[jRow];
          if (pivotValue)
            break;
          jRow = pivotLinked[jRow];
        }
        assert(jRow == smallestIndex);
      }
#endif
#if ABC_PARALLEL == 0
      //smallestIndex=pivotLinkedForwardsAddress_[-1];
      updateColumnTransposeU(regionSparse, smallestIndex
#if ABC_SMALL < 2
        ,
        reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
      );
#else
      assert(FACTOR_CPU > 3);
      updateColumnTransposeU(regionSparse, smallestIndex
#if ABC_SMALL < 2
        ,
        reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
          ,
        3);
#endif
    }
  } else {
#endif
#if ABC_SMALL >= 0
    // No row copy check space
    CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_;
    CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_);
    CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_);
    nInRow = replaceColumnU(regionSparse, deletedPosition, deletedColumns, pivotRow);
#endif
#if ABC_SMALL < 2
  }
#endif
}
#ifdef ABC_LONG_FACTORIZATION
long
#endif
  double
  CoinAbcTypeFactorization::checkReplacePart1b(CoinIndexedVector *regionSparse,
    int pivotRow)
{
  if (lengthR_ + numberRows_ >= lengthAreaR_) {
    //not enough room
    return 0.0;
  }
#ifdef ABC_USE_FUNCTION_POINTERS
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
  CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU;
  CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2);
#else
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
  CoinBigIndex startU = startColumnU[numberRows_];
  CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_];
#endif
  if (lengthU_ + numberInColumnU2 >= lengthAreaU_) {
    //not enough room
    return 0.0;
  }
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices (  );
  //CoinSimplexInt status=0;

  //int numberNonZero = regionSparse->getNumElements (  );
  //printf("replace nels %d\n",numberNonZero);
  CoinFactorizationDouble saveFromU = 0.0;

  for (CoinBigIndex i = 0; i < numberInColumnU2; i++) {
    CoinSimplexInt iRow = indexU2[i];
    if (iRow != pivotRow) {
      saveFromU -= elementU2[i] * region[iRow];
    } else {
      saveFromU += elementU2[i];
    }
  }
  return saveFromU;
}
#endif
#include "AbcSimplex.hpp"
/* Checks if can replace one Column to basis,
   returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */
int CoinAbcTypeFactorization::checkReplacePart2(int pivotRow,
  CoinSimplexDouble /*btranAlpha*/, CoinSimplexDouble ftranAlpha,
#ifdef ABC_LONG_FACTORIZATION
  long
#endif
  double ftAlpha,
  double /*acceptablePivot*/)
{
  if (lengthR_ + numberRows_ >= lengthAreaR_) {
    //not enough room
    return 3;
  }
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  CoinFactorizationDouble oldPivot = pivotRegion[pivotRow];
  // for accuracy check
  CoinFactorizationDouble pivotCheck = ftranAlpha / oldPivot;
  //check accuracy
  int status = checkPivot(ftAlpha, pivotCheck);
  if (status == 1 && !numberPivots_) {
    printf("check status ok\n");
    status = 2;
  }
  return status;
}
/* Replaces one Column to basis,
   partial update already in U */
void CoinAbcTypeFactorization::replaceColumnPart3(const AbcSimplex * /*model*/,
  CoinIndexedVector *regionSparse,
  CoinIndexedVector * /*tableauColumn*/,
  int pivotRow,
#ifdef ABC_LONG_FACTORIZATION
  long
#endif
  double alpha)
{
  assert(numberU_ <= numberRowsExtra_);
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT permuteLookup = pivotColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);

  //take out old pivot column

#ifndef ABC_USE_FUNCTION_POINTERS
  totalElements_ -= numberInColumn[pivotRow];
#else
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
#if ABC_USE_FUNCTION_POINTERS
  extern scatterUpdate AbcScatterLowSubtract[9];
  extern scatterUpdate AbcScatterHighSubtract[4];
#endif
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = scatter[numberRows_].offset;
  totalElements_ -= scatter[pivotRow].number;
  CoinBigIndex saveStart = scatter[pivotRow].offset;
  CoinBigIndex saveEnd = scatter[pivotRow].number;
  scatter[pivotRow].offset = startU;
  CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU;
  CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2);
#endif
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#if CONVERTROW > 2
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  CoinFactorizationDouble pivotValue = 1.0;
  CoinSimplexInt status = 0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif
  CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_;

#ifndef NDEBUG
#if CONVERTROW
#define CONVERTDEBUG
#endif
#endif
  int nInRow = 9999999; // ? what if ABC_SMALL==0 or ABC_SMALL==1
#if ABC_SMALL < 2
  CoinBigIndex start = 0;
  CoinBigIndex end = 0;
  if (gotUCopy()) {
    start = startRowU[pivotRow];
    nInRow = numberInRowU[pivotRow];
    end = start + nInRow;
  }
#endif
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  numberNonZero = regionSparse->getNumElements();
  //CoinFactorizationDouble saveFromU = 0.0;

#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex startU = startColumnU[numberRows_];
  startColumnU[pivotRow] = startU;
  CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_];
#else
//CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number;
#endif
  instrument_do("CoinAbcFactorizationReplaceColumn", 2 * numberRows_ + 4 * numberInColumnU2);
  pivotValue = 1.0 / alpha;
#if ABC_SMALL < 2
  if (gotUCopy()) {
    for (CoinBigIndex i = start; i < end; i++) {
      CoinSimplexInt jColumn = indexColumnU[i];
#ifndef ABC_USE_FUNCTION_POINTERS
      CoinBigIndex startColumn = startColumnU[jColumn];
#if CONVERTROW
      CoinBigIndex j = convertRowToColumn[i];
#else
      CoinBigIndex j;
      int number = numberInColumn[jColumn];
      for (j = 0; j < number; j++) {
        if (indexRowU[j + startColumn] == pivotRow)
          break;
      }
      assert(j < number);
      //assert (j==convertRowToColumn[i]); // temp
#endif
#ifdef CONVERTDEBUG
      assert(fabs(elementU[j + startColumn] - elementRowU[i]) < 1.0e-4);
#endif
#else
      int number = scatter[jColumn].number;
      CoinSimplexInt k = number - 1;
      scatter[jColumn].number = k;
      CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
      CoinSimplexInt *COIN_RESTRICT indices = reinterpret_cast< CoinSimplexInt * >(area + k + 1);
#if CONVERTROW
      CoinSimplexInt j = convertRowToColumn[i];
#else
      CoinSimplexInt j;
      for (j = 0; j < number; j++) {
        if (indices[j] == pivotRow)
          break;
      }
      assert(j < number);
      //assert (j==convertRowToColumn[i]); // temp
#endif
#ifdef CONVERTDEBUG
      assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#endif
#endif
      // swap
#ifndef ABC_USE_FUNCTION_POINTERS
      CoinSimplexInt k = numberInColumn[jColumn] - 1;
      numberInColumn[jColumn] = k;
      CoinBigIndex k2 = k + startColumn;
      int kRow2 = indexRowU[k2];
      indexRowU[j + startColumn] = kRow2;
      CoinFactorizationDouble value2 = elementU[k2];
      elementU[j + startColumn] = value2;
#else
      int kRow2 = indices[k];
      CoinFactorizationDouble value2 = area[k];
#if ABC_USE_FUNCTION_POINTERS
      if (k < 9) {
        scatter[jColumn].functionPointer = AbcScatterLowSubtract[k];
      } else {
        scatter[jColumn].functionPointer = AbcScatterHighSubtract[k & 3];
      }
#endif
      // later more complicated swap to avoid move (don't think we can!)
      indices[j] = kRow2;
      area[j] = value2;
      // move
      indices -= 2;
      for (int i = 0; i < k; i++)
        indices[i] = indices[i + 2];
#endif
      // move in row copy (slow - as other remark (but shouldn't need to))
      CoinBigIndex start2 = startRowU[kRow2];
      int n = numberInRowU[kRow2];
      CoinBigIndex end2 = start2 + n;
#ifndef NDEBUG
      bool found = false;
#endif
      for (CoinBigIndex i2 = start2; i2 < end2; i2++) {
        CoinSimplexInt iColumn2 = indexColumnU[i2];
        if (jColumn == iColumn2) {
#if CONVERTROW
          convertRowToColumn[i2] = j;
#endif
#ifndef NDEBUG
          found = true;
#endif
          break;
        }
      }
#ifndef NDEBUG
      assert(found);
#endif
    }
  } else {
#endif
#if ABC_SMALL >= 0
    assert(nInRow != 9999999); // ? what if ABC_SMALL==0 or ABC_SMALL==1
    // no row copy
    CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_);
    CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_);
    for (CoinSimplexInt i = 0; i < nInRow; i++) {
      CoinBigIndex j = deletedPosition[i];
      CoinSimplexInt jColumn = deletedColumns[i];
      // swap
      CoinSimplexInt k = numberInColumn[jColumn] - 1;
      numberInColumn[jColumn] = k;
      CoinBigIndex k2 = k + startColumnU[jColumn];
      int kRow2 = indexRowU[k2];
      indexRowU[j] = kRow2;
      CoinFactorizationDouble value2 = elementU[k2];
      elementU[j] = value2;
    }
#endif
#if ABC_SMALL < 2
  }
#endif
#if ABC_SMALL < 2
  if (gotUCopy()) {
    // Now zero out column of U
    //take out old pivot column
#ifdef ABC_USE_FUNCTION_POINTERS
    CoinFactorizationDouble *COIN_RESTRICT elementU = elementUColumnPlus + saveStart;
    saveStart = 0;
    CoinSimplexInt *COIN_RESTRICT indexRowU = reinterpret_cast< CoinSimplexInt * >(elementU + saveEnd);
#endif
    for (CoinBigIndex i = saveStart; i < saveEnd; i++) {
      //elementU[i] = 0.0;
      // If too slow then reverse meaning of convertRowToColumn and use
      int jRow = indexRowU[i];
      CoinBigIndex start = startRowU[jRow];
      CoinBigIndex end = start + numberInRowU[jRow];
      for (CoinBigIndex j = start; j < end; j++) {
        CoinSimplexInt jColumn = indexColumnU[j];
        if (jColumn == pivotRow) {
          // swap
          numberInRowU[jRow]--;
          elementRowU[j] = elementRowU[end - 1];
#if CONVERTROW
          convertRowToColumn[j] = convertRowToColumn[end - 1];
#endif
          indexColumnU[j] = indexColumnU[end - 1];
          break;
        }
      }
    }
  }
#endif
  //zero out pivot Row (before or after?)
  //add to R
  CoinBigIndex *COIN_RESTRICT startColumnR = startColumnRAddress_;
  CoinBigIndex putR = lengthR_;
  CoinSimplexInt number = numberR_;

  startColumnR[number] = putR; //for luck and first time
  number++;
  //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2));
  startColumnR[number] = putR + numberNonZero;
  numberR_ = number;
  lengthR_ = putR + numberNonZero;
  totalElements_ += numberNonZero;

#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT nextRow = NULL;
  CoinSimplexInt *COIN_RESTRICT lastRow = NULL;
  CoinSimplexInt next;
  CoinSimplexInt last;
  if (gotUCopy()) {
    //take out row
    nextRow = nextRowAddress_;
    lastRow = lastRowAddress_;
    next = nextRow[pivotRow];
    last = lastRow[pivotRow];

    nextRow[last] = next;
    lastRow[next] = last;
    numberInRowU[pivotRow] = 0;
  }
#endif
  //put in pivot
  //add row counts

  int n = 0;
  for (CoinSimplexInt i = 0; i < numberInColumnU2; i++) {
    CoinSimplexInt iRow = indexU2[i];
    CoinFactorizationDouble value = elementU2[i];
    assert(value);
    if (!TEST_LESS_THAN_TOLERANCE(value)) {
      if (iRow != pivotRow) {
        //modify by pivot
        CoinFactorizationDouble value2 = value * pivotValue;
        indexU2[n] = iRow;
        elementU2[n++] = value2;
#if ABC_SMALL < 2
        if (gotUCopy()) {
          CoinSimplexInt next = nextRow[iRow];
          CoinSimplexInt iNumberInRow = numberInRowU[iRow];
          CoinBigIndex space;
          CoinBigIndex put = startRowU[iRow] + iNumberInRow;
          space = startRowU[next] - put;
          if (space <= 0) {
            getRowSpaceIterate(iRow, iNumberInRow + 4);
            put = startRowU[iRow] + iNumberInRow;
          } else if (next == numberRows_) {
            lastEntryByRowU_ = put + 1;
          }
          indexColumnU[put] = pivotRow;
#if CONVERTROW
          convertRowToColumn[put] = i;
#endif
          elementRowU[put] = value2;
          numberInRowU[iRow] = iNumberInRow + 1;
        }
#endif
      } else {
        //swap and save
        indexU2[i] = indexU2[numberInColumnU2 - 1];
        elementU2[i] = elementU2[numberInColumnU2 - 1];
        numberInColumnU2--;
        i--;
      }
    } else {
      // swap
      indexU2[i] = indexU2[numberInColumnU2 - 1];
      elementU2[i] = elementU2[numberInColumnU2 - 1];
      numberInColumnU2--;
      i--;
    }
  }
  numberInColumnU2 = n;
  //do permute
  permuteAddress_[numberRowsExtra_] = pivotRow;
  //and for safety
  permuteAddress_[numberRowsExtra_ + 1] = 0;

  //pivotColumnAddress_[pivotRow] = numberRowsExtra_;

  numberU_++;

#if ABC_SMALL < 2
  if (gotUCopy()) {
    //in at end
    last = lastRow[numberRows_];
    nextRow[last] = pivotRow; //numberRowsExtra_;
    lastRow[numberRows_] = pivotRow; //numberRowsExtra_;
    lastRow[pivotRow] = last;
    nextRow[pivotRow] = numberRows_;
    startRowU[pivotRow] = lastEntryByRowU_;
  }
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  numberInColumn[pivotRow] = numberInColumnU2;
#else
#if ABC_USE_FUNCTION_POINTERS
  if (numberInColumnU2 < 9) {
    scatter[pivotRow].functionPointer = AbcScatterLowSubtract[numberInColumnU2];
  } else {
    scatter[pivotRow].functionPointer = AbcScatterHighSubtract[numberInColumnU2 & 3];
  }
#endif
  assert(scatter[pivotRow].offset == lastEntryByColumnUPlus_);
  //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_;
  //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+numberInColumnU2);
  if (numberInColumnU2 < scatter[numberRows_].number) {
    int offset = 2 * (scatter[numberRows_].number - numberInColumnU2);
    indexU2 -= offset;
    //assert(indexU2-reinterpret_cast<int*>(area)>=0);
    for (int i = 0; i < numberInColumnU2; i++)
      indexU2[i] = indexU2[i + offset];
  }
  scatter[pivotRow].number = numberInColumnU2;
  //CoinAbcMemcpy(indices,indexU2,numberInColumnU2);
  //CoinAbcMemcpy(area,elementU2,numberInColumnU2);
  lastEntryByColumnUPlus_ += (3 * numberInColumnU2 + 1) >> 1;
#endif
  totalElements_ += numberInColumnU2;
  lengthU_ += numberInColumnU2;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;
  if (gotRCopy()) {
    //column in at beginning (as empty)
    next = nextColumn[maximumRowsExtra_];
    lastColumn[next] = numberRowsExtra_;
    nextColumn[maximumRowsExtra_] = numberRowsExtra_;
    nextColumn[numberRowsExtra_] = next;
    lastColumn[numberRowsExtra_] = maximumRowsExtra_;
  }
#endif
#if 0
  {
    int k=-1;
    for (int i=0;i<numberRows_;i++) {
      k=CoinMax(k,startRowU[i]+numberInRowU[i]);
    }
    assert (k==lastEntryByRowU_);
  }
#endif
  //pivotRegion[numberRowsExtra_] = pivotValue;
  pivotRegion[pivotRow] = pivotValue;
#ifndef ABC_USE_FUNCTION_POINTERS
  maximumU_ = CoinMax(maximumU_, startU + numberInColumnU2);
#else
  maximumU_ = CoinMax(maximumU_, lastEntryByColumnUPlus_);
#endif
  permuteLookup[pivotRow] = numberRowsExtra_;
  permuteLookup[numberRowsExtra_] = pivotRow;
  //pivotColumnAddress_[pivotRow]=numberRowsExtra_;
  //pivotColumnAddress_[numberRowsExtra_]=pivotRow;
  assert(pivotRow < numberRows_);
  // out of chain
  CoinSimplexInt iLast = pivotLinkedBackwardsAddress_[pivotRow];
  CoinSimplexInt iNext = pivotLinkedForwardsAddress_[pivotRow];
  assert(pivotRow == pivotLinkedForwardsAddress_[iLast]);
  assert(pivotRow == pivotLinkedBackwardsAddress_[iNext]);
  pivotLinkedForwardsAddress_[iLast] = iNext;
  pivotLinkedBackwardsAddress_[iNext] = iLast;
  if (pivotRow == lastSlack_) {
    lastSlack_ = iLast;
  }
  iLast = pivotLinkedBackwardsAddress_[numberRows_];
  assert(numberRows_ == pivotLinkedForwardsAddress_[iLast]);
  pivotLinkedForwardsAddress_[iLast] = pivotRow;
  pivotLinkedBackwardsAddress_[pivotRow] = iLast;
  pivotLinkedBackwardsAddress_[numberRows_] = pivotRow;
  pivotLinkedForwardsAddress_[pivotRow] = numberRows_;
  assert(numberRows_ > pivotLinkedForwardsAddress_[-1]);
  assert(pivotLinkedBackwardsAddress_[numberRows_] >= 0);
  numberRowsExtra_++;
  numberGoodU_++;
  numberPivots_++;
  if (numberRowsExtra_ > numberRows_ + 50) {
    CoinBigIndex extra = factorElements_ >> 1;

    if (numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500) {
      if (extra < 2 * numberRows_) {
        extra = 2 * numberRows_;
      }
    } else {
      if (extra < 5 * numberRows_) {
        extra = 5 * numberRows_;
      }
    }
    CoinBigIndex added = totalElements_ - factorElements_;

    if (added > extra && added > (factorElements_) << 1 && !status
      && 3 * totalElements_ > 2 * (lengthAreaU_ + lengthAreaL_)) {
      status = 3;
      if (messageLevel_ & 4) {
        std::cout << "Factorization has " << totalElements_
                  << ", basis had " << factorElements_ << std::endl;
      }
    }
  }
#if ABC_SMALL < 2
  if (gotRCopy() && status < 2) {
    //if (numberInColumnPlus&&status<2) {
    // we are going to put another copy of R in R
    CoinFactorizationDouble *COIN_RESTRICT elementRR = elementRAddress_ + lengthAreaR_;
    CoinSimplexInt *COIN_RESTRICT indexRowRR = indexRowRAddress_ + lengthAreaR_;
    CoinBigIndex *COIN_RESTRICT startRR = startColumnRAddress_ + maximumPivots_ + 1;
    CoinSimplexInt pivotRow = numberRowsExtra_ - 1;
    for (CoinBigIndex i = 0; i < numberNonZero; i++) {
      CoinSimplexInt jRow = regionIndex[i];
      CoinFactorizationDouble value = region[jRow];
      elementR[putR] = value;
      indexRowR[putR] = jRow;
      putR++;
      region[jRow] = 0.0;
      int iRow = permuteLookup[jRow];
      next = nextColumn[iRow];
      CoinBigIndex space;
      if (next != maximumRowsExtra_)
        space = startRR[next] - startRR[iRow];
      else
        space = lengthAreaR_ - startRR[iRow];
      CoinSimplexInt numberInR = numberInColumnPlus[iRow];
      if (space > numberInR) {
        // there is space
        CoinBigIndex put = startRR[iRow] + numberInR;
        numberInColumnPlus[iRow] = numberInR + 1;
        indexRowRR[put] = pivotRow;
        elementRR[put] = value;
        //add 4 for luck
        if (next == maximumRowsExtra_)
          startRR[maximumRowsExtra_] = CoinMin(static_cast< CoinBigIndex >(put + 4), lengthAreaR_);
      } else {
        // no space - do we shuffle?
        if (!getColumnSpaceIterateR(iRow, value, pivotRow)) {
          // printf("Need more space for R\n");
          numberInColumnPlus_.conditionalDelete();
          numberInColumnPlusAddress_ = NULL;
          setNoGotRCopy();
          regionSparse->clear();
#if ABC_SMALL < 0
          abort();
          status = 3;
#endif
          break;
        }
      }
    }
  } else {
#endif
    for (CoinBigIndex i = 0; i < numberNonZero; i++) {
      CoinSimplexInt iRow = regionIndex[i];
      elementR[putR] = region[iRow];
      region[iRow] = 0.0;
      indexRowR[putR] = iRow;
      putR++;
    }
#if ABC_SMALL < 2
  }
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
#if 0
  {
    CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
    extern scatterUpdate AbcScatterLowSubtract[9];
    extern scatterUpdate AbcScatterHighSubtract[4];
    printf("=============================================start\n");
    for (int iRow=0;iRow<numberRows_;iRow++) {
      int number=scatter[iRow].number;
      CoinBigIndex offset = scatter[iRow].offset;
      CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+offset;
      CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+number);
      CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow];
      CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow];
      //assert (number==numberInColumn[iRow]);
#if ABC_USE_FUNCTION_POINTERS
      if (number<9)
	assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]);
      else
	assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]);
#endif
      if (number)
	printf("Row %d %d els\n",iRow,number);
      int n=0;
      for (int i=0;i<number;i++) {
	printf("(%d,%g) ",indices[i],area[i]);
	n++;
	if (n==10) {
	  n=0;
	  printf("\n");
	}
      }
      if (n)
	printf("\n");
#if 0
      for (int i=0;i<number;i++) {
	assert (indices[i]==indices2[i]);
	assert (area[i]==area2[i]);
      }
#endif
    }
    printf("=============================================end\n");
  }
#endif
#endif
  regionSparse->setNumElements(0);
  fromLongArray(regionSparse);
#if 0
  static int arrayF[6]={1,1,1,1,1,1};
  static int arrayB[6]={1,1,1,1,1,1};
  static int arrayF1[6]={1,1,1,1,1,1};
  static int arrayB1[6]={1,1,1,1,1,1};
  static int itry=0;
  {
    const CoinSimplexInt *  COIN_RESTRICT back = firstCountAddress_+numberRows_;
    const CoinSimplexInt *  COIN_RESTRICT pivotColumn = pivotColumnAddress_; // no
    const CoinSimplexInt *  COIN_RESTRICT permute = permuteAddress_;
    const CoinSimplexInt *  COIN_RESTRICT pivotLOrder = this->pivotLOrderAddress_;
    const CoinSimplexInt *  COIN_RESTRICT pivotLinkedForwards = this->pivotLinkedForwardsAddress_;//no
    const CoinSimplexInt *  COIN_RESTRICT pivotLinkedBackwards = this->pivotLinkedBackwardsAddress_;//no
    itry++;
    int testit[6];
    for (int i=0;i<6;i++) 
      testit[i]=1;
    for (int i=0;i<numberRows_;i++) {
      if (back[i]!=i)
	testit[0]=0;
      if (pivotColumn[i]!=i)
	testit[1]=0;
      if (permute[i]!=i)
	testit[2]=0;
      if (pivotLOrder[i]!=i)
	testit[3]=0;
      if (pivotLinkedForwards[i]!=i)
	testit[4]=0;
      if (pivotLinkedBackwards[i]!=i)
	testit[5]=0;
    }
    for (int i=0;i<6;i++) {
      if (!testit[i])
	arrayF[i]=0;
    }
    for (int i=0;i<6;i++) 
      testit[i]=1;
    for (int i=0;i<numberRows_;i++) {
      if (back[i]!=(numberRows_-1-i))
	testit[0]=0;
      if (pivotColumn[i]!=(numberRows_-1-i))
	testit[1]=0;
      if (permute[i]!=(numberRows_-1-i))
	testit[2]=0;
      if (pivotLOrder[i]!=(numberRows_-1-i))
	testit[3]=0;
      if (pivotLinkedForwards[i]!=(numberRows_-1-i))
	testit[4]=0;
      if (pivotLinkedBackwards[i]!=(numberRows_-1-i))
	testit[5]=0;
    }
    for (int i=0;i<6;i++) {
      if (!testit[i])
	arrayB[i]=0;
    }
    for (int i=0;i<6;i++) 
      testit[i]=1;
    for (int i=0;i<numberRows_-1;i++) {
      if (back[i]!=(i+1))
	testit[0]=0;
      if (pivotColumn[i]!=(i+1))
	testit[1]=0;
      if (permute[i]!=(i+1))
	testit[2]=0;
      if (pivotLOrder[i]!=(i+1))
	testit[3]=0;
      if (pivotLinkedForwards[i]!=(i+1))
	testit[4]=0;
      if (pivotLinkedBackwards[i]!=(i+1))
	testit[5]=0;
    }
    for (int i=0;i<6;i++) {
      if (!testit[i])
	arrayF1[i]=0;
    }
    for (int i=0;i<6;i++) 
      testit[i]=1;
    for (int i=0;i<numberRows_-1;i++) {
      if (back[i]!=pivotLinkedBackwards[i-1])
	testit[0]=0;
      if (pivotColumn[i]!=(numberRows_-i-2))
	testit[1]=0;
      if (permute[i]!=(numberRows_-i-2))
	testit[2]=0;
      if (pivotLOrder[i]!=(numberRows_-i-2))
	testit[3]=0;
      if (pivotLinkedForwards[i]!=(numberRows_-i-2))
	testit[4]=0;
      if (pivotLinkedBackwards[i]!=i-1)
	testit[5]=0;
    }
    for (int i=0;i<6;i++) {
      if (!testit[i])
	arrayB1[i]=0;
    }
    if ((itry%1000)==0) {
      for (int i=0;i<6;i++) {
	if (arrayF[i])
	  printf("arrayF[%d] still active\n",i);
	if (arrayB[i])
	  printf("arrayB[%d] still active\n",i);
	if (arrayF1[i])
	  printf("arrayF1[%d] still active\n",i);
	if (arrayB1[i])
	  printf("arrayB1[%d] still active\n",i);
      }
    }
  }
#endif
}
/* Replaces one Column to basis,
   partial update in vector */
void CoinAbcTypeFactorization::replaceColumnPart3(const AbcSimplex * /*model*/,
  CoinIndexedVector *regionSparse,
  CoinIndexedVector * /*tableauColumn*/,
  CoinIndexedVector *partialUpdate,
  int pivotRow,
#ifdef ABC_LONG_FACTORIZATION
  long
#endif
  double alpha)
{
  assert(numberU_ <= numberRowsExtra_);
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_;
  CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_;
#endif
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT permuteLookup = pivotColumnAddress_;
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);

  CoinSimplexInt numberInColumnU2 = partialUpdate->getNumElements();
  //take out old pivot column

#ifndef ABC_USE_FUNCTION_POINTERS
  totalElements_ -= numberInColumn[pivotRow];
  CoinBigIndex startU = startColumnU[numberRows_];
  startColumnU[pivotRow] = startU;
  CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU];
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU];
  numberInColumn[numberRows_] = numberInColumnU2;
#else
  scatterStruct *COIN_RESTRICT scatter = scatterUColumn();
#if ABC_USE_FUNCTION_POINTERS
  extern scatterUpdate AbcScatterLowSubtract[9];
  extern scatterUpdate AbcScatterHighSubtract[4];
#endif
  CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
  CoinBigIndex startU = lastEntryByColumnUPlus_;
  totalElements_ -= scatter[pivotRow].number;
  CoinBigIndex saveStart = scatter[pivotRow].offset;
  CoinBigIndex saveEnd = scatter[pivotRow].number;
  scatter[pivotRow].offset = startU;

  scatter[numberRows_].number = numberInColumnU2;
  CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU;
  CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2);
#endif
  // move
  CoinSimplexInt *COIN_RESTRICT indexU2Save = partialUpdate->getIndices();
  CoinFactorizationDouble *COIN_RESTRICT elementU2Save = denseVector(partialUpdate);
  memcpy(indexU2, indexU2Save, numberInColumnU2 * sizeof(CoinSimplexInt));
  for (int i = 0; i < numberInColumnU2; i++) {
    int iRow = indexU2[i];
    elementU2[i] = elementU2Save[iRow];
    elementU2Save[iRow] = 0.0;
  }
  //memcpy(elementU2,elementU2Save,numberInColumnU2*sizeof(double));
  //memset(elementU2Save,0,numberInColumnU2*sizeof(double));
  partialUpdate->setNumElements(0);
  //get entries in row (pivot not stored)
  CoinSimplexInt numberNonZero = 0;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_;
#endif
#if CONVERTROW
  CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_;
#if CONVERTROW > 2
  CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_;
#endif
#endif
#if ABC_SMALL < 2
  CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;
  CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_;
#endif
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  CoinFactorizationDouble pivotValue = 1.0;
  CoinSimplexInt status = 0;
#ifndef ABC_USE_FUNCTION_POINTERS
  CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_;
#endif
  CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_;

#ifndef NDEBUG
#if CONVERTROW
#define CONVERTDEBUG
#endif
#endif
  int nInRow = 9999999; // ? what if ABC_SMALL==0 or ABC_SMALL==1
#if ABC_SMALL < 2
  CoinBigIndex start = 0;
  CoinBigIndex end = 0;
  if (gotUCopy()) {
    start = startRowU[pivotRow];
    nInRow = numberInRowU[pivotRow];
    end = start + nInRow;
  }
#endif
  CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;
  numberNonZero = regionSparse->getNumElements();
  //CoinFactorizationDouble saveFromU = 0.0;

  instrument_do("CoinAbcFactorizationReplaceColumn", 2 * numberRows_ + 4 * numberInColumnU2);
  pivotValue = 1.0 / alpha;
#if ABC_SMALL < 2
  if (gotUCopy()) {
    for (CoinBigIndex i = start; i < end; i++) {
      CoinSimplexInt jColumn = indexColumnU[i];
#ifndef ABC_USE_FUNCTION_POINTERS
      CoinBigIndex startColumn = startColumnU[jColumn];
#if CONVERTROW
      CoinBigIndex j = convertRowToColumn[i];
#else
      CoinBigIndex j;
      int number = numberInColumn[jColumn];
      for (j = 0; j < number; j++) {
        if (indexRowU[j + startColumn] == pivotRow)
          break;
      }
      assert(j < number);
      //assert (j==convertRowToColumn[i]); // temp
#endif
#ifdef CONVERTDEBUG
      assert(fabs(elementU[j + startColumn] - elementRowU[i]) < 1.0e-4);
#endif
#else
      int number = scatter[jColumn].number;
      CoinSimplexInt k = number - 1;
      scatter[jColumn].number = k;
      CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset;
      CoinSimplexInt *COIN_RESTRICT indices = reinterpret_cast< CoinSimplexInt * >(area + k + 1);
#if CONVERTROW
      CoinSimplexInt j = convertRowToColumn[i];
#else
      CoinSimplexInt j;
      for (j = 0; j < number; j++) {
        if (indices[j] == pivotRow)
          break;
      }
      assert(j < number);
      //assert (j==convertRowToColumn[i]); // temp
#endif
#ifdef CONVERTDEBUG
      assert(fabs(area[j] - elementRowU[i]) < 1.0e-4);
#endif
#endif
      // swap
#ifndef ABC_USE_FUNCTION_POINTERS
      CoinSimplexInt k = numberInColumn[jColumn] - 1;
      numberInColumn[jColumn] = k;
      CoinBigIndex k2 = k + startColumn;
      int kRow2 = indexRowU[k2];
      indexRowU[j + startColumn] = kRow2;
      CoinFactorizationDouble value2 = elementU[k2];
      elementU[j + startColumn] = value2;
#else
      int kRow2 = indices[k];
      CoinFactorizationDouble value2 = area[k];
#if ABC_USE_FUNCTION_POINTERS
      if (k < 9) {
        scatter[jColumn].functionPointer = AbcScatterLowSubtract[k];
      } else {
        scatter[jColumn].functionPointer = AbcScatterHighSubtract[k & 3];
      }
#endif
      // later more complicated swap to avoid move (don't think we can!)
      indices[j] = kRow2;
      area[j] = value2;
      // move
      indices -= 2;
      for (int i = 0; i < k; i++)
        indices[i] = indices[i + 2];
#endif
      // move in row copy (slow - as other remark (but shouldn't need to))
      CoinBigIndex start2 = startRowU[kRow2];
      int n = numberInRowU[kRow2];
      CoinBigIndex end2 = start2 + n;
#ifndef NDEBUG
      bool found = false;
#endif
      for (CoinBigIndex i2 = start2; i2 < end2; i2++) {
        CoinSimplexInt iColumn2 = indexColumnU[i2];
        if (jColumn == iColumn2) {
#if CONVERTROW
          convertRowToColumn[i2] = j;
#endif
#ifndef NDEBUG
          found = true;
#endif
          break;
        }
      }
#ifndef NDEBUG
      assert(found);
#endif
    }
  } else {
#endif
#if ABC_SMALL >= 0
    assert(nInRow != 9999999); // ? what if ABC_SMALL==0 or ABC_SMALL==1
    // no row copy
    CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_);
    CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_);
    for (CoinSimplexInt i = 0; i < nInRow; i++) {
      CoinBigIndex j = deletedPosition[i];
      CoinSimplexInt jColumn = deletedColumns[i];
      // swap
      CoinSimplexInt k = numberInColumn[jColumn] - 1;
      numberInColumn[jColumn] = k;
      CoinBigIndex k2 = k + startColumnU[jColumn];
      int kRow2 = indexRowU[k2];
      indexRowU[j] = kRow2;
      CoinFactorizationDouble value2 = elementU[k2];
      elementU[j] = value2;
    }
#endif
#if ABC_SMALL < 2
  }
#endif
#if ABC_SMALL < 2
  if (gotUCopy()) {
    // Now zero out column of U
    //take out old pivot column
#ifdef ABC_USE_FUNCTION_POINTERS
    CoinFactorizationDouble *COIN_RESTRICT elementU = elementUColumnPlus + saveStart;
    saveStart = 0;
    CoinSimplexInt *COIN_RESTRICT indexRowU = reinterpret_cast< CoinSimplexInt * >(elementU + saveEnd);
#endif
    for (CoinBigIndex i = saveStart; i < saveEnd; i++) {
      //elementU[i] = 0.0;
      // If too slow then reverse meaning of convertRowToColumn and use
      int jRow = indexRowU[i];
      CoinBigIndex start = startRowU[jRow];
      CoinBigIndex end = start + numberInRowU[jRow];
      for (CoinBigIndex j = start; j < end; j++) {
        CoinSimplexInt jColumn = indexColumnU[j];
        if (jColumn == pivotRow) {
          // swap
          numberInRowU[jRow]--;
          elementRowU[j] = elementRowU[end - 1];
#if CONVERTROW
          convertRowToColumn[j] = convertRowToColumn[end - 1];
#endif
          indexColumnU[j] = indexColumnU[end - 1];
          break;
        }
      }
    }
  }
#endif
  //zero out pivot Row (before or after?)
  //add to R
  CoinBigIndex *COIN_RESTRICT startColumnR = startColumnRAddress_;
  CoinBigIndex putR = lengthR_;
  CoinSimplexInt number = numberR_;

  startColumnR[number] = putR; //for luck and first time
  number++;
  //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2));
  startColumnR[number] = putR + numberNonZero;
  numberR_ = number;
  lengthR_ = putR + numberNonZero;
  totalElements_ += numberNonZero;

#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT nextRow = NULL;
  CoinSimplexInt *COIN_RESTRICT lastRow = NULL;
  CoinSimplexInt next;
  CoinSimplexInt last;
  if (gotUCopy()) {
    //take out row
    nextRow = nextRowAddress_;
    lastRow = lastRowAddress_;
    next = nextRow[pivotRow];
    last = lastRow[pivotRow];

    nextRow[last] = next;
    lastRow[next] = last;
    numberInRowU[pivotRow] = 0;
  }
#endif
  //put in pivot
  //add row counts

  int n = 0;
  for (CoinSimplexInt i = 0; i < numberInColumnU2; i++) {
    CoinSimplexInt iRow = indexU2[i];
    CoinFactorizationDouble value = elementU2[i];
    assert(value);
    if (!TEST_LESS_THAN_TOLERANCE(value)) {
      if (iRow != pivotRow) {
        //modify by pivot
        CoinFactorizationDouble value2 = value * pivotValue;
        indexU2[n] = iRow;
        elementU2[n++] = value2;
#if ABC_SMALL < 2
        if (gotUCopy()) {
          CoinSimplexInt next = nextRow[iRow];
          CoinSimplexInt iNumberInRow = numberInRowU[iRow];
          CoinBigIndex space;
          CoinBigIndex put = startRowU[iRow] + iNumberInRow;
          space = startRowU[next] - put;
          if (space <= 0) {
            getRowSpaceIterate(iRow, iNumberInRow + 4);
            put = startRowU[iRow] + iNumberInRow;
          } else if (next == numberRows_) {
            lastEntryByRowU_ = put + 1;
          }
          indexColumnU[put] = pivotRow;
#if CONVERTROW
          convertRowToColumn[put] = i;
#endif
          elementRowU[put] = value2;
          numberInRowU[iRow] = iNumberInRow + 1;
        }
#endif
      } else {
        //swap and save
        indexU2[i] = indexU2[numberInColumnU2 - 1];
        elementU2[i] = elementU2[numberInColumnU2 - 1];
        numberInColumnU2--;
        i--;
      }
    } else {
      // swap
      indexU2[i] = indexU2[numberInColumnU2 - 1];
      elementU2[i] = elementU2[numberInColumnU2 - 1];
      numberInColumnU2--;
      i--;
    }
  }
  numberInColumnU2 = n;
  //do permute
  permuteAddress_[numberRowsExtra_] = pivotRow;
  //and for safety
  permuteAddress_[numberRowsExtra_ + 1] = 0;

  //pivotColumnAddress_[pivotRow] = numberRowsExtra_;

  numberU_++;

#if ABC_SMALL < 2
  if (gotUCopy()) {
    //in at end
    last = lastRow[numberRows_];
    nextRow[last] = pivotRow; //numberRowsExtra_;
    lastRow[numberRows_] = pivotRow; //numberRowsExtra_;
    lastRow[pivotRow] = last;
    nextRow[pivotRow] = numberRows_;
    startRowU[pivotRow] = lastEntryByRowU_;
  }
#endif
#ifndef ABC_USE_FUNCTION_POINTERS
  numberInColumn[pivotRow] = numberInColumnU2;
#else
#if ABC_USE_FUNCTION_POINTERS
  if (numberInColumnU2 < 9) {
    scatter[pivotRow].functionPointer = AbcScatterLowSubtract[numberInColumnU2];
  } else {
    scatter[pivotRow].functionPointer = AbcScatterHighSubtract[numberInColumnU2 & 3];
  }
#endif
  assert(scatter[pivotRow].offset == lastEntryByColumnUPlus_);
  //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_;
  //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+numberInColumnU2);
  if (numberInColumnU2 < scatter[numberRows_].number) {
    int offset = 2 * (scatter[numberRows_].number - numberInColumnU2);
    indexU2 -= offset;
    //assert(indexU2-reinterpret_cast<int*>(area)>=0);
    for (int i = 0; i < numberInColumnU2; i++)
      indexU2[i] = indexU2[i + offset];
  }
  scatter[pivotRow].number = numberInColumnU2;
  //CoinAbcMemcpy(indices,indexU2,numberInColumnU2);
  //CoinAbcMemcpy(area,elementU2,numberInColumnU2);
  lastEntryByColumnUPlus_ += (3 * numberInColumnU2 + 1) >> 1;
#endif
  totalElements_ += numberInColumnU2;
  lengthU_ += numberInColumnU2;
#if ABC_SMALL < 2
  CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_;
  CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_;
  if (gotRCopy()) {
    //column in at beginning (as empty)
    next = nextColumn[maximumRowsExtra_];
    lastColumn[next] = numberRowsExtra_;
    nextColumn[maximumRowsExtra_] = numberRowsExtra_;
    nextColumn[numberRowsExtra_] = next;
    lastColumn[numberRowsExtra_] = maximumRowsExtra_;
  }
#endif
#if 0
  {
    int k=-1;
    for (int i=0;i<numberRows_;i++) {
      k=CoinMax(k,startRowU[i]+numberInRowU[i]);
    }
    assert (k==lastEntryByRowU_);
  }
#endif
  //pivotRegion[numberRowsExtra_] = pivotValue;
  pivotRegion[pivotRow] = pivotValue;
#ifndef ABC_USE_FUNCTION_POINTERS
  maximumU_ = CoinMax(maximumU_, startU + numberInColumnU2);
#else
  maximumU_ = CoinMax(maximumU_, lastEntryByColumnUPlus_);
#endif
  permuteLookup[pivotRow] = numberRowsExtra_;
  permuteLookup[numberRowsExtra_] = pivotRow;
  //pivotColumnAddress_[pivotRow]=numberRowsExtra_;
  //pivotColumnAddress_[numberRowsExtra_]=pivotRow;
  assert(pivotRow < numberRows_);
  // out of chain
  CoinSimplexInt iLast = pivotLinkedBackwardsAddress_[pivotRow];
  CoinSimplexInt iNext = pivotLinkedForwardsAddress_[pivotRow];
  assert(pivotRow == pivotLinkedForwardsAddress_[iLast]);
  assert(pivotRow == pivotLinkedBackwardsAddress_[iNext]);
  pivotLinkedForwardsAddress_[iLast] = iNext;
  pivotLinkedBackwardsAddress_[iNext] = iLast;
  if (pivotRow == lastSlack_) {
    lastSlack_ = iLast;
  }
  iLast = pivotLinkedBackwardsAddress_[numberRows_];
  assert(numberRows_ == pivotLinkedForwardsAddress_[iLast]);
  pivotLinkedForwardsAddress_[iLast] = pivotRow;
  pivotLinkedBackwardsAddress_[pivotRow] = iLast;
  pivotLinkedBackwardsAddress_[numberRows_] = pivotRow;
  pivotLinkedForwardsAddress_[pivotRow] = numberRows_;
  assert(numberRows_ > pivotLinkedForwardsAddress_[-1]);
  assert(pivotLinkedBackwardsAddress_[numberRows_] >= 0);
  numberRowsExtra_++;
  numberGoodU_++;
  numberPivots_++;
  if (numberRowsExtra_ > numberRows_ + 50) {
    CoinBigIndex extra = factorElements_ >> 1;

    if (numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500) {
      if (extra < 2 * numberRows_) {
        extra = 2 * numberRows_;
      }
    } else {
      if (extra < 5 * numberRows_) {
        extra = 5 * numberRows_;
      }
    }
    CoinBigIndex added = totalElements_ - factorElements_;

    if (added > extra && added > (factorElements_) << 1 && !status
      && 3 * totalElements_ > 2 * (lengthAreaU_ + lengthAreaL_)) {
      status = 3;
      if (messageLevel_ & 4) {
        std::cout << "Factorization has " << totalElements_
                  << ", basis had " << factorElements_ << std::endl;
      }
    }
  }
#if ABC_SMALL < 2
  if (gotRCopy() && status < 2) {
    //if (numberInColumnPlus&&status<2) {
    // we are going to put another copy of R in R
    CoinFactorizationDouble *COIN_RESTRICT elementRR = elementRAddress_ + lengthAreaR_;
    CoinSimplexInt *COIN_RESTRICT indexRowRR = indexRowRAddress_ + lengthAreaR_;
    CoinBigIndex *COIN_RESTRICT startRR = startColumnRAddress_ + maximumPivots_ + 1;
    CoinSimplexInt pivotRow = numberRowsExtra_ - 1;
    for (CoinBigIndex i = 0; i < numberNonZero; i++) {
      CoinSimplexInt jRow = regionIndex[i];
      CoinFactorizationDouble value = region[jRow];
      elementR[putR] = value;
      indexRowR[putR] = jRow;
      putR++;
      region[jRow] = 0.0;
      int iRow = permuteLookup[jRow];
      next = nextColumn[iRow];
      CoinBigIndex space;
      if (next != maximumRowsExtra_)
        space = startRR[next] - startRR[iRow];
      else
        space = lengthAreaR_ - startRR[iRow];
      CoinSimplexInt numberInR = numberInColumnPlus[iRow];
      if (space > numberInR) {
        // there is space
        CoinBigIndex put = startRR[iRow] + numberInR;
        numberInColumnPlus[iRow] = numberInR + 1;
        indexRowRR[put] = pivotRow;
        elementRR[put] = value;
        //add 4 for luck
        if (next == maximumRowsExtra_)
          startRR[maximumRowsExtra_] = CoinMin(static_cast< CoinBigIndex >(put + 4), lengthAreaR_);
      } else {
        // no space - do we shuffle?
        if (!getColumnSpaceIterateR(iRow, value, pivotRow)) {
          // printf("Need more space for R\n");
          numberInColumnPlus_.conditionalDelete();
          numberInColumnPlusAddress_ = NULL;
          setNoGotRCopy();
          regionSparse->clear();
#if ABC_SMALL < 0
          abort();
          status = 3;
#endif
          break;
        }
      }
    }
  } else {
#endif
    for (CoinBigIndex i = 0; i < numberNonZero; i++) {
      CoinSimplexInt iRow = regionIndex[i];
      elementR[putR] = region[iRow];
      region[iRow] = 0.0;
      indexRowR[putR] = iRow;
      putR++;
    }
#if ABC_SMALL < 2
  }
#endif
#ifdef ABC_USE_FUNCTION_POINTERS
#if 0
  {
    CoinFactorizationDouble *  COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_;
    CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_;
    CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_;
    CoinSimplexInt *  COIN_RESTRICT numberInColumn = numberInColumnAddress_;
    CoinBigIndex *  COIN_RESTRICT startColumnU = startColumnUAddress_;
    scatterStruct * COIN_RESTRICT scatter = scatterUColumn();
    extern scatterUpdate AbcScatterLowSubtract[9];
    extern scatterUpdate AbcScatterHighSubtract[4];
    printf("=============================================start\n");
    for (int iRow=0;iRow<numberRows_;iRow++) {
      int number=scatter[iRow].number;
      CoinBigIndex offset = scatter[iRow].offset;
      CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+offset;
      CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast<CoinSimplexInt *>(area+number);
      CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow];
      CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow];
      //assert (number==numberInColumn[iRow]);
#if ABC_USE_FUNCTION_POINTERS
      if (number<9)
	assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]);
      else
	assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]);
#endif
      if (number)
	printf("Row %d %d els\n",iRow,number);
      int n=0;
      for (int i=0;i<number;i++) {
	printf("(%d,%g) ",indices[i],area[i]);
	n++;
	if (n==10) {
	  n=0;
	  printf("\n");
	}
      }
      if (n)
	printf("\n");
#if 0
      for (int i=0;i<number;i++) {
	assert (indices[i]==indices2[i]);
	assert (area[i]==area2[i]);
      }
#endif
    }
    printf("=============================================end\n");
  }
#endif
#endif
  regionSparse->setNumElements(0);
}
#if ABC_SMALL >= 0
/* Combines BtranU and store which elements are to be deleted
 */
int CoinAbcTypeFactorization::replaceColumnU(CoinIndexedVector *regionSparse,
  CoinBigIndex *deletedPosition,
  CoinSimplexInt *deletedColumns,
  CoinSimplexInt pivotRow)
{
  instrument_start("CoinAbcFactorizationReplaceColumnU", numberRows_);
  CoinSimplexDouble *COIN_RESTRICT region = regionSparse->denseVector();
  int *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_;
  const CoinSimplexInt COIN_RESTRICT *indexRow = indexRowUAddress_;
  CoinFactorizationDouble COIN_RESTRICT *element = elementUAddress_;
  int numberNonZero = 0;
  const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_;
  int nPut = 0;
  const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
  CoinSimplexInt jRow = pivotLinked[-1];
  while (jRow != numberRows_) {
    assert(!region[jRow]);
    CoinFactorizationDouble pivotValue = 0.0;
    instrument_add(numberInColumn[jRow]);
    for (CoinBigIndex j = startColumn[jRow];
         j < startColumn[jRow] + numberInColumn[jRow]; j++) {
      int iRow = indexRow[j];
      CoinFactorizationDouble value = element[j];
      if (iRow != pivotRow) {
        pivotValue -= value * region[iRow];
      } else {
        assert(!region[iRow]);
        pivotValue += value;
        deletedColumns[nPut] = jRow;
        deletedPosition[nPut++] = j;
      }
    }
    if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) {
      regionIndex[numberNonZero++] = jRow;
      region[jRow] = pivotValue;
    } else {
      region[jRow] = 0;
    }
    jRow = pivotLinked[jRow];
  }
  regionSparse->setNumElements(numberNonZero);
  instrument_end();
  return nPut;
}
/* Updates part of column transpose (BTRANU) by column
   assumes index is sorted i.e. region is correct */
void CoinAbcTypeFactorization::updateColumnTransposeUByColumn(CoinIndexedVector *regionSparse,
  CoinSimplexInt smallestIndex) const
{
  instrument_start("CoinAbcFactorizationUpdateTransposeUByColumn", numberRows_);
  CoinSimplexDouble *COIN_RESTRICT region = regionSparse->denseVector();
  const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_;
  const CoinSimplexInt COIN_RESTRICT *indexRow = indexRowUAddress_;
  const CoinFactorizationDouble COIN_RESTRICT *element = elementUAddress_;
#if ABC_SMALL < 3
  int numberNonZero = 0;
  int *COIN_RESTRICT regionIndex = regionSparse->getIndices();
#endif
  const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_;
  //const CoinFactorizationDouble COIN_RESTRICT *pivotRegion = pivotRegionAddress_;
  const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
  CoinSimplexInt jRow = smallestIndex;
  while (jRow != numberRows_) {
    CoinFactorizationDouble pivotValue = region[jRow];
    CoinBigIndex start = startColumn[jRow];
    instrument_add(numberInColumn[jRow]);
#ifndef INLINE_IT2
    for (CoinBigIndex j = start; j < start + numberInColumn[jRow]; j++) {
      int iRow = indexRow[j];
      CoinFactorizationDouble value = element[j];
      pivotValue -= value * region[iRow];
    }
#else
    pivotValue += CoinAbcGatherUpdate(numberInColumn[jRow], element + start, indexRow + start, region);
#endif
#if ABC_SMALL < 3
    if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) {
      regionIndex[numberNonZero++] = jRow;
      region[jRow] = pivotValue;
    } else {
      region[jRow] = 0;
    }
#else
    region[jRow] = pivotValue;
#endif
    jRow = pivotLinked[jRow];
  }
#if ABC_SMALL < 3
  regionSparse->setNumElements(numberNonZero);
#endif
  instrument_end();
}
#endif
//  updateColumnTranspose.  Updates one column transpose (BTRAN)
CoinSimplexInt
CoinAbcTypeFactorization::updateColumnTranspose(CoinIndexedVector &regionSparse) const
{
  toLongArray(&regionSparse, 0);
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse.getIndices();
  CoinSimplexInt numberNonZero = regionSparse.getNumElements();
  const CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_;

#ifndef ABC_ORDERED_FACTORIZATION
  // can I move this
#ifndef INLINE_IT3
  for (CoinSimplexInt i = 0; i < numberNonZero; i++) {
    CoinSimplexInt iRow = regionIndex[i];
    CoinSimplexDouble value = region[iRow];
    value *= pivotRegion[iRow];
    region[iRow] = value;
  }
#else
  multiplyIndexed(numberNonZero, pivotRegion,
    regionIndex, region);
#endif
#else
  // Permute in for Btran
  permuteInForBtranAndMultiply(regionSparse);
#endif
  //  ******* U
  // Apply pivot region - could be combined for speed
  // Can only combine/move inside vector for sparse
  CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1];
#if ABC_SMALL < 2
  // copy of code inside transposeU
  bool goSparse = false;
#else
#define goSparse false
#endif
#if ABC_SMALL < 2
  // Guess at number at end
  if (gotUCopy()) {
    assert(btranAverageAfterU_);
    CoinSimplexInt newNumber = static_cast< CoinSimplexInt >(numberNonZero * btranAverageAfterU_ * twiddleBtranFactor1());
    if (newNumber < sparseThreshold_)
      goSparse = true;
  }
#endif
#if 0
  static int xxxxxx=0;
  xxxxxx++;
  if (xxxxxx%20==0) {
    int smallestK=-1;
    int largestK=-1;
    //const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_;
    CoinSimplexInt *  COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_;
    for (CoinSimplexInt k = numberRows_-1 ; k >= 0; k-- ) {
      CoinSimplexInt i=pivotRowForward[k];
      if (numberInColumn[i]) {
	if (largestK<0)
	  largestK=k;
	smallestK=k;
      }
    }
    printf("UByCol %d slacks largestK %d smallestK %d\n",numberSlacks_,largestK,smallestK);
    //const CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_;
    const CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_;
    smallestK=-1;
    largestK=-1;
    for (CoinSimplexInt k = numberRows_-1 ; k >= 0; k-- ) {
      CoinSimplexInt i=pivotRowForward[k];
      if (numberInRow[i]) {
	if (largestK<0)
	  largestK=k;
	smallestK=k;
      }
    }
    printf("and ByRow largestK %d smallestK %d\n",largestK,smallestK);
  }
#endif
  if (numberNonZero < 40 && (numberNonZero << 4) < numberRows_ && !goSparse) {
    CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_;
    CoinSimplexInt smallest = numberRowsExtra_;
    for (CoinSimplexInt j = 0; j < numberNonZero; j++) {
      CoinSimplexInt iRow = regionIndex[j];
      if (pivotRowForward[iRow] < smallest) {
        smallest = pivotRowForward[iRow];
        smallestIndex = iRow;
      }
    }
  }
  updateColumnTransposeU(&regionSparse, smallestIndex
#if ABC_SMALL < 2
    ,
    reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
#if ABC_PARALLEL
      ,
    0
#endif
  );
  //row bits here
  updateColumnTransposeR(&regionSparse
#if ABC_SMALL < 2
    ,
    reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
  );
  //  ******* L
  updateColumnTransposeL(&regionSparse
#if ABC_SMALL < 2
    ,
    reinterpret_cast< CoinAbcStatistics & >(btranCountInput_)
#endif
#if ABC_PARALLEL
      ,
    0
#endif
  );
#if ABC_SMALL < 3
#ifdef ABC_ORDERED_FACTORIZATION
  // Permute out for Btran
  permuteOutForBtran(regionSparse);
#endif
#if ABC_DEBUG
  regionSparse.checkClean();
#endif
  numberNonZero = regionSparse.getNumElements();
#else
  numberNonZero = 0;
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
    CoinExponent expValue = ABC_EXPONENT(region[i]);
    if (expValue) {
      if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) {
        regionIndex[numberNonZero++] = i;
      } else {
        region[i] = 0.0;
      }
    }
  }
  regionSparse.setNumElements(numberNonZero);
#endif
  fromLongArray(static_cast< int >(0));
  return numberNonZero;
}
#if ABC_SMALL < 2

/* Updates part of column transpose (BTRANU) when densish,
   assumes index is sorted i.e. region is correct */
void CoinAbcTypeFactorization::updateColumnTransposeUDensish(CoinIndexedVector *regionSparse,
  CoinSimplexInt smallestIndex) const
{
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt numberNonZero = regionSparse->getNumElements();

  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();

  const CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
  const CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;
  const CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;

  const CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;

  numberNonZero = 0;
  const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_;
  CoinSimplexInt jRow = smallestIndex; //pivotLinked[-1];
  instrument_start("CoinAbcFactorizationUpdateTransposeUDensish", numberRows_);
  while (jRow >= 0) {
    if (TEST_DOUBLE_NONZERO(region[jRow])) {
      CoinFactorizationDouble pivotValue = region[jRow];
      if (!TEST_LESS_THAN_UPDATE_TOLERANCE(pivotValue)) {
        CoinSimplexInt numberIn = numberInRow[jRow];
        instrument_add(numberIn);
        if (TEST_INT_NONZERO(numberIn)) {
          CoinBigIndex start = startRow[jRow];
          CoinBigIndex end = start + numberIn;
#ifndef INLINE_IT
          for (CoinBigIndex j = start; j < end; j++) {
            CoinSimplexInt iRow = indexColumn[j];
            CoinFactorizationDouble value = elementRowU[j];
            assert(value);
            // i<iRow
            region[iRow] -= value * pivotValue;
          }
#else
          CoinAbcScatterUpdate(end - start, pivotValue, elementRowU + start, indexColumn + start, region);
#endif
        }
        regionIndex[numberNonZero++] = jRow;
      } else {
        region[jRow] = 0.0;
      }
    }
    jRow = pivotLinked[jRow];
  }
  //set counts
  regionSparse->setNumElements(numberNonZero);
  instrument_end();
}
/* Updates part of column transpose (BTRANU) when sparse,
   assumes index is sorted i.e. region is correct */
void CoinAbcTypeFactorization::updateColumnTransposeUSparse(
  CoinIndexedVector *regionSparse
#if ABC_PARALLEL
  ,
  int whichSparse
#endif
  ) const
{
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt numberNonZero = regionSparse->getNumElements();

  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  const CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_;
  const CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_;
  const CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_;

  const CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_;

  // use sparse_ as temporary area
  // mark known to be zero
  //printf("PP 0_ %d %s\n",__LINE__,__FILE__);
  CoinAbcStack *COIN_RESTRICT stackList = reinterpret_cast< CoinAbcStack * >(sparseAddress_);
  CoinSimplexInt *COIN_RESTRICT list = listAddress_;
  CoinCheckZero *COIN_RESTRICT mark = markRowAddress_;
#if ABC_PARALLEL
  //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__);
  if (whichSparse) {
    //printf("alternative sparse\n");
    int addAmount = whichSparse * sizeSparseArray_;
    stackList = reinterpret_cast< CoinAbcStack * >(reinterpret_cast< char * >(stackList) + addAmount);
    list = reinterpret_cast< CoinSimplexInt * >(reinterpret_cast< char * >(list) + addAmount);
    mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + addAmount);
  }
#endif
  CoinSimplexInt nList;
#if 0 //ndef NDEBUG
  for (CoinSimplexInt i=0;i<numberRows_;i++) {
#if 0
    assert (!mark[i]);
#else
    if (mark[i]) {
      printf("HHHHHHHHHHelp %d %d\n",i,mark[i]);
      usleep(10000000);
    }
#endif
  }
#endif
  nList = 0;
  for (CoinSimplexInt k = 0; k < numberNonZero; k++) {
    CoinSimplexInt kPivot = regionIndex[k];
    stackList[0].stack = kPivot;
    CoinSimplexInt jPivot = kPivot;
    CoinBigIndex start = startRow[jPivot];
    stackList[0].next = start + numberInRow[jPivot] - 1;
    stackList[0].start = start;
    CoinSimplexInt nStack = 1;
    while (nStack) {
      /* take off stack */
      kPivot = stackList[--nStack].stack;
      if (mark[kPivot] != 1) {
#if 0
	CoinBigIndex j=stackList[nStack].next;
	CoinBigIndex startThis=stackList[nStack].start;
	for (;j>=startThis;j--) {
	  CoinSimplexInt kPivot3=indexColumn[j--];
	  if (!mark[kPivot3]) {
	    kPivot=kPivot3;
	    break;
	  }
	}
	if (j>=startThis) {
	  /* put back on stack */
	  stackList[nStack++].next =j;
	  /* and new one */
	  CoinBigIndex start=startRow[kPivot];
	  j=start+numberInRow[kPivot]-1;
	  stackList[nStack].stack=kPivot;
	  stackList[nStack].start=start;
	  mark[kPivot]=2;
	  stackList[nStack++].next=j;
#else
        CoinBigIndex j = stackList[nStack].next;
        if (j >= stackList[nStack].start) {
          CoinSimplexInt kPivot3 = indexColumn[j--];
          /* put back on stack */
          stackList[nStack++].next = j;
          if (!mark[kPivot3]) {
            /* and new one */
            CoinBigIndex start = startRow[kPivot3];
            j = start + numberInRow[kPivot3] - 1;
            stackList[nStack].stack = kPivot3;
            stackList[nStack].start = start;
            mark[kPivot3] = 2;
            stackList[nStack++].next = j;
          }
#endif
      } else {
        // finished
        list[nList++] = kPivot;
        mark[kPivot] = 1;
      }
    }
  }
}
instrument_start("CoinAbcFactorizationUpdateTransposeUSparse", 2 * (numberNonZero + nList));
numberNonZero = 0;
for (CoinSimplexInt i = nList - 1; i >= 0; i--) {
  CoinSimplexInt iPivot = list[i];
  assert(iPivot >= 0 && iPivot < numberRows_);
  mark[iPivot] = 0;
  CoinFactorizationDouble pivotValue = region[iPivot];
  if (!TEST_LESS_THAN_UPDATE_TOLERANCE(pivotValue)) {
    CoinSimplexInt numberIn = numberInRow[iPivot];
    instrument_add(numberIn);
    if (TEST_INT_NONZERO(numberIn)) {
      CoinBigIndex start = startRow[iPivot];
#ifndef INLINE_IT
      CoinBigIndex end = start + numberIn;
      for (CoinBigIndex j = start; j < end; j++) {
        CoinSimplexInt iRow = indexColumn[j];
        CoinFactorizationDouble value = elementRowU[j];
        region[iRow] -= value * pivotValue;
      }
#else
        CoinAbcScatterUpdate(numberIn, pivotValue, elementRowU + start, indexColumn + start, region);
#endif
    }
    regionIndex[numberNonZero++] = iPivot;
  } else {
    region[iPivot] = 0.0;
  }
}
//set counts
regionSparse->setNumElements(numberNonZero);
instrument_end_and_adjust(1.3);
}
#endif
//  updateColumnTransposeU.  Updates part of column transpose (BTRANU)
//assumes index is sorted i.e. region is correct
//does not sort by sign
void CoinAbcTypeFactorization::updateColumnTransposeU(CoinIndexedVector *regionSparse,
  CoinSimplexInt smallestIndex
#if ABC_SMALL < 2
  ,
  CoinAbcStatistics &statistics
#endif
#if ABC_PARALLEL
  ,
  int whichCpu
#endif
  ) const
{
#if CILK_CONFLICT > 0
#if ABC_PARALLEL
  // for conflicts
#if CILK_CONFLICT > 1
  printf("file %s line %d which %d\n", __FILE__, __LINE__, whichCpu);
#endif
  abc_assert((cilk_conflict & (1 << whichCpu)) == 0);
  cilk_conflict |= (1 << whichCpu);
#else
  abc_assert((cilk_conflict & (1 << 0)) == 0);
  cilk_conflict |= (1 << 0);
#endif
#endif
#if ABC_SMALL < 2
  CoinSimplexInt number = regionSparse->getNumElements();
  if (factorizationStatistics()) {
    statistics.numberCounts_++;
    statistics.countInput_ += static_cast< CoinSimplexDouble >(number);
  }
  CoinSimplexInt goSparse;
  // Guess at number at end
  if (gotUCopy()) {
    if (gotSparse()) {
      assert(statistics.averageAfterU_);
      CoinSimplexInt newNumber = static_cast< CoinSimplexInt >(number * statistics.averageAfterU_ * twiddleBtranFactor1());
      if (newNumber < sparseThreshold_)
        goSparse = 2;
      else
        goSparse = 0;
    } else {
      goSparse = 0;
    }
#if ABC_SMALL >= 0
  } else {
    goSparse = -1;
#endif
  }
  //CoinIndexedVector temp(*regionSparse);
  switch (goSparse) {
#if ABC_SMALL >= 0
  case -1: // no row copy
    updateColumnTransposeUByColumn(regionSparse, smallestIndex);
    break;
#endif
  case 0: // densish
    updateColumnTransposeUDensish(regionSparse, smallestIndex);
    break;
  case 2: // sparse
  {
    updateColumnTransposeUSparse(regionSparse
#if ABC_PARALLEL
      ,
      whichCpu
#endif
    );
  } break;
  }
  if (factorizationStatistics())
    statistics.countAfterU_ += static_cast< CoinSimplexDouble >(regionSparse->getNumElements());
#else
  updateColumnTransposeUByColumn(regionSparse, smallestIndex);
#endif
#if CILK_CONFLICT > 0
#if ABC_PARALLEL
  // for conflicts
  abc_assert((cilk_conflict & (1 << whichCpu)) != 0);
  cilk_conflict &= ~(1 << whichCpu);
#else
  abc_assert((cilk_conflict & (1 << 0)) != 0);
  cilk_conflict &= ~(1 << 0);
#endif
#endif
}

/*  updateColumnTransposeLDensish.  
    Updates part of column transpose (BTRANL) dense by column */
void CoinAbcTypeFactorization::updateColumnTransposeLDensish(CoinIndexedVector *regionSparse) const
{
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt base;
  CoinSimplexInt first = -1;
  const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_;
  //const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_;

#if ABC_SMALL < 3
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  CoinSimplexInt numberNonZero = 0;
#endif
  //scan
  for (first = numberRows_ - 1; first >= 0; first--) {
#ifndef ABC_ORDERED_FACTORIZATION
    if (region[pivotLOrder[first]])
      break;
#else
    if (region[first])
      break;
#endif
  }
  instrument_start("CoinAbcFactorizationUpdateTransposeLDensish", first);
  if (first >= 0) {
    base = baseL_;
    const CoinBigIndex *COIN_RESTRICT startColumn = startColumnLAddress_;
    const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowLAddress_;
    const CoinFactorizationDouble *COIN_RESTRICT element = elementLAddress_;
    CoinSimplexInt last = baseL_ + numberL_;

    if (first >= last) {
      first = last - 1;
    }
    CoinBigIndex end = startColumn[first + 1];
    for (CoinSimplexInt k = first; k >= base; k--) {
#ifndef ABC_ORDERED_FACTORIZATION
      CoinSimplexInt i = pivotLOrder[k];
#else
      CoinSimplexInt i = k;
#endif
      CoinFactorizationDouble pivotValue = region[i];
#ifndef INLINE_IT2
      CoinBigIndex j = end - 1;
      end = startColumn[k];
      instrument_add(j - end);
      for (; j >= end; j--) {
        CoinSimplexInt iRow = indexRow[j];
        CoinFactorizationDouble value = element[j];
        pivotValue -= value * region[iRow];
      }
#else
      CoinBigIndex start = startColumn[k];
      instrument_add(end - start);
      pivotValue += CoinAbcGatherUpdate(end - start, element + start, indexRow + start, region);
      end = start;
#endif
#if ABC_SMALL < 3
      if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) {
        region[i] = pivotValue;
        regionIndex[numberNonZero++] = i;
      } else {
        region[i] = 0.0;
      }
#else
      region[i] = pivotValue;
#endif
    }
#if ABC_SMALL < 3
    //may have stopped early
    if (first < base) {
      base = first + 1;
    }

    for (CoinSimplexInt k = base - 1; k >= 0; k--) {
#ifndef ABC_ORDERED_FACTORIZATION
      CoinSimplexInt i = pivotLOrder[k];
#else
      CoinSimplexInt i = k;
#endif
      CoinExponent expValue = ABC_EXPONENT(region[i]);
      if (expValue) {
        if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) {
          regionIndex[numberNonZero++] = i;
        } else {
          region[i] = 0.0;
        }
      }
    }
#endif
  }
#if ABC_SMALL < 3
  //set counts
  regionSparse->setNumElements(numberNonZero);
#endif
  instrument_end();
}
#if ABC_SMALL < 2
/*  updateColumnTransposeLByRow. 
    Updates part of column transpose (BTRANL) densish but by row */
void CoinAbcTypeFactorization::updateColumnTransposeLByRow(CoinIndexedVector *regionSparse) const
{
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  CoinSimplexInt numberNonZero;

  // use row copy of L
  const CoinFactorizationDouble *COIN_RESTRICT element = elementByRowLAddress_;
  const CoinBigIndex *COIN_RESTRICT startRow = startRowLAddress_;
  const CoinSimplexInt *COIN_RESTRICT column = indexColumnLAddress_;
  const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_;
  numberNonZero = 0;
  instrument_start("CoinAbcFactorizationUpdateTransposeLByRow", numberRows_ + numberSlacks_);
  // down to slacks
  for (CoinSimplexInt k = numberRows_ - 1; k >= numberSlacks_; k--) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt i = pivotLOrder[k];
#else
    CoinSimplexInt i = k;
#endif
    if (TEST_DOUBLE_NONZERO(region[i])) {
      CoinFactorizationDouble pivotValue = region[i];
      if (!TEST_LESS_THAN_TOLERANCE(pivotValue)) {
        regionIndex[numberNonZero++] = i;
        CoinBigIndex start = startRow[i];
        CoinBigIndex end = startRow[i + 1];
        instrument_add(end - start);
        if (TEST_INT_NONZERO(end - start)) {
#ifndef INLINE_IT
          for (CoinBigIndex j = end - 1; j >= start; j--) {
            CoinSimplexInt iRow = column[j];
            CoinFactorizationDouble value = element[j];
            region[iRow] -= pivotValue * value;
          }
#else
          CoinAbcScatterUpdate(end - start, pivotValue, element + start, column + start, region);
#endif
        }
      } else {
        region[i] = 0.0;
      }
    }
  }
  for (CoinSimplexInt k = numberSlacks_ - 1; k >= 0; k--) {
#ifndef ABC_ORDERED_FACTORIZATION
    CoinSimplexInt i = pivotLOrder[k];
#else
    CoinSimplexInt i = k;
#endif
    CoinExponent expValue = ABC_EXPONENT(region[i]);
    if (expValue) {
      if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) {
        regionIndex[numberNonZero++] = i;
      } else {
        region[i] = 0.0;
      }
    }
  }
  //set counts
  regionSparse->setNumElements(numberNonZero);
  instrument_end();
}
/*  updateColumnTransposeLSparse. 
    Updates part of column transpose (BTRANL) sparse */
void CoinAbcTypeFactorization::updateColumnTransposeLSparse(CoinIndexedVector *regionSparse
#if ABC_PARALLEL
  ,
  int whichSparse
#endif
  ) const
{
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  CoinSimplexInt numberNonZero = regionSparse->getNumElements();

  // use row copy of L
  const CoinFactorizationDouble *COIN_RESTRICT element = elementByRowLAddress_;
  const CoinBigIndex *COIN_RESTRICT startRow = startRowLAddress_;
  const CoinSimplexInt *COIN_RESTRICT column = indexColumnLAddress_;
  // use sparse_ as temporary area
  // mark known to be zero
  //printf("PP 0_ %d %s\n",__LINE__,__FILE__);
  CoinAbcStack *COIN_RESTRICT stackList = reinterpret_cast< CoinAbcStack * >(sparseAddress_);
  CoinSimplexInt *COIN_RESTRICT list = listAddress_;
  CoinCheckZero *COIN_RESTRICT mark = markRowAddress_;
#if ABC_PARALLEL
  //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__);
  if (whichSparse) {
    int addAmount = whichSparse * sizeSparseArray_;
    //printf("alternative sparse\n");
    stackList = reinterpret_cast< CoinAbcStack * >(reinterpret_cast< char * >(stackList) + addAmount);
    list = reinterpret_cast< CoinSimplexInt * >(reinterpret_cast< char * >(list) + addAmount);
    mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + addAmount);
  }
#endif
#ifndef NDEBUG
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
#if 0
    assert (!mark[i]);
#else
    if (mark[i]) {
      printf("HHHHHHHHHHelp2 %d %d\n", i, mark[i]);
      usleep(10000000);
    }
#endif
  }
#endif
  CoinSimplexInt nList;
  CoinSimplexInt number = numberNonZero;
  nList = 0;
  for (CoinSimplexInt k = 0; k < number; k++) {
    CoinSimplexInt kPivot = regionIndex[k];
    //CoinSimplexInt iPivot=pivotLBackwardOrder[kPivot];
    if (!mark[kPivot] && region[kPivot]) {
      stackList[0].stack = kPivot;
      stackList[0].start = startRow[kPivot];
      CoinBigIndex j = startRow[kPivot + 1] - 1;
      CoinSimplexInt nStack = 0;
      while (nStack >= 0) {
        /* take off stack */
        if (j >= stackList[nStack].start) {
          CoinSimplexInt jPivot = column[j--];
          /* put back on stack */
          stackList[nStack].next = j;
          if (!mark[jPivot]) {
            /* and new one */
            kPivot = jPivot;
            //iPivot=pivotLBackwardOrder[kPivot];
            j = startRow[kPivot + 1] - 1;
            stackList[++nStack].stack = kPivot;
            mark[kPivot] = 1;
            stackList[nStack].start = startRow[kPivot];
            stackList[nStack].next = j;
          }
        } else {
          /* finished so mark */
          list[nList++] = kPivot;
          mark[kPivot] = 1;
          --nStack;
          if (nStack >= 0) {
            kPivot = stackList[nStack].stack;
            j = stackList[nStack].next;
          }
        }
      }
    }
  }
  instrument_start("CoinAbcFactorizationUpdateTransposeLSparse", 2 * (numberNonZero + nList));
  numberNonZero = 0;
  for (CoinSimplexInt i = nList - 1; i >= 0; i--) {
    CoinSimplexInt iPivot = list[i];
    //CoinSimplexInt kPivot=pivotLOrder[iPivot];
    mark[iPivot] = 0;
    CoinFactorizationDouble pivotValue = region[iPivot];
    if (!TEST_LESS_THAN_TOLERANCE(pivotValue)) {
      regionIndex[numberNonZero++] = iPivot;
      CoinBigIndex start = startRow[iPivot];
      CoinBigIndex end = startRow[iPivot + 1];
      instrument_add(end - start);
#ifndef INLINE_IT
      CoinBigIndex j;
      for (j = start; j < end; j++) {
        CoinSimplexInt iRow = column[j];
        CoinFactorizationDouble value = element[j];
        region[iRow] -= value * pivotValue;
      }
#else
      CoinAbcScatterUpdate(end - start, pivotValue, element + start, column + start, region);
#endif
    } else {
      region[iPivot] = 0.0;
    }
  }
  //set counts
  regionSparse->setNumElements(numberNonZero);
  instrument_end_and_adjust(1.3);
}
#endif
//  updateColumnTransposeL.  Updates part of column transpose (BTRANL)
void CoinAbcTypeFactorization::updateColumnTransposeL(CoinIndexedVector *regionSparse
#if ABC_SMALL < 2
  ,
  CoinAbcStatistics &statistics
#endif
#if ABC_PARALLEL
  ,
  int whichSparse
#endif
  ) const
{
#if CILK_CONFLICT > 0
#if ABC_PARALLEL
  // for conflicts
#if CILK_CONFLICT > 1
  printf("file %s line %d which %d\n", __FILE__, __LINE__, whichSparse);
#endif
  abc_assert((cilk_conflict & (1 << whichSparse)) == 0);
  cilk_conflict |= (1 << whichSparse);
#else
  abc_assert((cilk_conflict & (1 << 0)) == 0);
  cilk_conflict |= (1 << 0);
#endif
#endif
#if ABC_SMALL < 3
  CoinSimplexInt number = regionSparse->getNumElements();
#endif
  if (!numberL_
#if ABC_SMALL < 4
    && !numberDense_
#endif
  ) {
#if ABC_SMALL < 3
    if (number >= numberRows_) {
      // need scan
      regionSparse->setNumElements(0);
      scan(regionSparse);
    }
#endif
#if CILK_CONFLICT > 0
#if ABC_PARALLEL
    // for conflicts
    abc_assert((cilk_conflict & (1 << whichSparse)) != 0);
    cilk_conflict &= ~(1 << whichSparse);
#else
    abc_assert((cilk_conflict & (1 << 0)) != 0);
    cilk_conflict &= ~(1 << 0);
#endif
#endif
    return;
  }
#if ABC_SMALL < 2
  CoinSimplexInt goSparse;
  // Guess at number at end
  // we may need to rethink on dense
  if (gotLCopy()) {
    assert(statistics.averageAfterL_);
    CoinSimplexInt newNumber = static_cast< CoinSimplexInt >(number * statistics.averageAfterL_ * twiddleBtranFactor1());
    if (newNumber < sparseThreshold_)
      goSparse = 2;
    else if (2 * newNumber < numberRows_)
      goSparse = 0;
    else
      goSparse = -1;
  } else {
    goSparse = -1;
  }
#endif
#if ABC_SMALL < 4
#if ABC_DENSE_CODE > 0
  if (numberDense_) {
    //take off list
    CoinSimplexInt lastSparse = numberRows_ - numberDense_;
    CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
    const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_;
    CoinFactorizationDouble *COIN_RESTRICT denseArea = denseAreaAddress_;
    CoinFactorizationDouble *COIN_RESTRICT denseRegion = denseArea + leadingDimension_ * numberDense_;
    CoinSimplexInt *COIN_RESTRICT densePermute = reinterpret_cast< CoinSimplexInt * >(denseRegion + FACTOR_CPU * numberDense_);
#if ABC_PARALLEL
    //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__);
    if (whichSparse)
      denseRegion += whichSparse * numberDense_;
#endif
    CoinFactorizationDouble *COIN_RESTRICT densePut = denseRegion - lastSparse;
    CoinZeroN(denseRegion, numberDense_);
    bool doDense = false;
#if ABC_SMALL < 3
    CoinSimplexInt number = regionSparse->getNumElements();
    CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
    const CoinSimplexInt *COIN_RESTRICT pivotLBackwardOrder = permuteAddress_;
    CoinSimplexInt i = 0;
#if ABC_SMALL < 0
    assert(number <= numberRows_);
#else
    if (number <= numberRows_) {
#endif
    while (i < number) {
      CoinSimplexInt iRow = regionIndex[i];
#ifndef ABC_ORDERED_FACTORIZATION
      CoinSimplexInt jRow = pivotLBackwardOrder[iRow];
#else
        CoinSimplexInt jRow = iRow;
#endif
      if (jRow >= lastSparse) {
        doDense = true;
        regionIndex[i] = regionIndex[--number];
        densePut[jRow] = region[iRow];
        region[iRow] = 0.0;
      } else {
        i++;
      }
    }
#endif
#if ABC_SMALL >= 0
#if ABC_SMALL < 3
  } else {
#endif
    for (CoinSimplexInt jRow = lastSparse; jRow < numberRows_; jRow++) {
      CoinSimplexInt iRow = pivotLOrder[jRow];
      if (region[iRow]) {
        doDense = true;
        densePut[jRow] = region[iRow];
        region[iRow] = 0.0;
      }
    }
#if ABC_SMALL < 3
    // numbers are all wrong - do a scan
    regionSparse->setNumElements(0);
    scan(regionSparse);
    number = regionSparse->getNumElements();
  }
#endif
#endif
  if (doDense) {
    instrument_do("CoinAbcFactorizationDenseTranspose", 0.25 * numberDense_ * numberDense_);
#if ABC_DENSE_CODE == 1
#ifndef CLAPACK
    char trans = 'T';
    CoinSimplexInt ione = 1;
    CoinSimplexInt info;
    F77_FUNC(dgetrs, DGETRS)
    (&trans, &numberDense_, &ione, denseArea, &leadingDimension_,
      densePermute, denseRegion, &numberDense_, &info, 1);
#else
        clapack_dgetrs(CblasColMajor, CblasTrans, numberDense_, 1,
          denseArea, leadingDimension_, densePermute, denseRegion, numberDense_);
#endif
#elif ABC_DENSE_CODE == 2
      CoinAbcDgetrs('T', numberDense_, denseArea, denseRegion);
      short *COIN_RESTRICT forBtran = reinterpret_cast< short * >(densePermute + numberDense_) + numberDense_ - lastSparse;
      pivotLOrder += lastSparse; // adjust
#endif
    for (CoinSimplexInt i = lastSparse; i < numberRows_; i++) {
      CoinSimplexDouble value = densePut[i];
      if (value) {
        if (!TEST_LESS_THAN_TOLERANCE(value)) {
#if ABC_DENSE_CODE != 2
          CoinSimplexInt iRow = pivotLOrder[i];
#else
            CoinSimplexInt iRow = pivotLOrder[forBtran[i]];
#endif
          region[iRow] = value;
#if ABC_SMALL < 3
          regionIndex[number++] = iRow;
#endif
        }
      }
    }
#if ABC_SMALL < 3
    regionSparse->setNumElements(number);
#endif
  }
}
//printRegion(*regionSparse,"After BtranL");
#endif
#endif
#if ABC_SMALL < 2
switch (goSparse) {
case -1: // No row copy
  updateColumnTransposeLDensish(regionSparse);
  break;
case 0: // densish but by row
  updateColumnTransposeLByRow(regionSparse);
  break;
case 2: // sparse
  updateColumnTransposeLSparse(regionSparse
#if ABC_PARALLEL
    ,
    whichSparse
#endif
  );
  break;
}
#else
  updateColumnTransposeLDensish(regionSparse);
#endif
#if CILK_CONFLICT > 0
#if ABC_PARALLEL
// for conflicts
abc_assert((cilk_conflict & (1 << whichSparse)) != 0);
cilk_conflict &= ~(1 << whichSparse);
#else
  abc_assert((cilk_conflict & (1 << 0)) != 0);
  cilk_conflict &= ~(1 << 0);
#endif
#endif
}
#if ABC_SMALL >= 0
// Updates part of column transpose (BTRANR) when dense
void CoinAbcTypeFactorization::updateColumnTransposeRDensish(CoinIndexedVector *regionSparse) const
{
  const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_;
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
#if ABC_SMALL < 3
#ifdef ABC_DEBUG
  regionSparse->checkClean();
#endif
#endif
  instrument_start("CoinAbcFactorizationUpdateTransposeRDensish", numberRows_);
  CoinSimplexInt last = numberRowsExtra_ - 1;
  const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_;
  const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_;
  const CoinSimplexInt *COIN_RESTRICT pivotRowBack = pivotColumnAddress_;
  for (CoinSimplexInt i = last; i >= numberRows_; i--) {
    CoinSimplexInt putRow = pivotRowBack[i];
    CoinFactorizationDouble pivotValue = region[putRow];
    if (pivotValue) {
      CoinBigIndex start = startColumn[i];
      CoinBigIndex end = startColumn[i + 1];
      instrument_add(end - start);
#ifndef INLINE_IT
      for (CoinBigIndex j = start; j < end; j++) {
        CoinFactorizationDouble value = element[j];
        CoinSimplexInt iRow = indexRow[j];
        assert(iRow < numberRows_);
        region[iRow] -= value * pivotValue;
      }
#else
      CoinAbcScatterUpdate(end - start, pivotValue, element + start, indexRow + start, region);
#endif
      region[putRow] = pivotValue;
    }
  }
  instrument_end();
}
#endif
#if ABC_SMALL < 2
// Updates part of column transpose (BTRANR) when sparse
void CoinAbcTypeFactorization::updateColumnTransposeRSparse(CoinIndexedVector *regionSparse) const
{
  CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse);
  CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices();
  CoinSimplexInt numberNonZero = regionSparse->getNumElements();
  instrument_start("CoinAbcFactorizationUpdateTransposeRSparse", numberRows_);

#if ABC_SMALL < 3
#ifdef ABC_DEBUG
  regionSparse->checkClean();
#endif
#endif
  CoinSimplexInt last = numberRowsExtra_ - 1;

  const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_;
  const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_;
  const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_;
  //move using lookup
  const CoinSimplexInt *COIN_RESTRICT pivotRowBack = pivotColumnAddress_;
  // still need to do in correct order (for now)
  for (CoinSimplexInt i = last; i >= numberRows_; i--) {
    CoinSimplexInt putRow = pivotRowBack[i];
    CoinFactorizationDouble pivotValue = region[putRow];
    if (pivotValue) {
      instrument_add(startColumn[i + 1] - startColumn[i]);
      for (CoinBigIndex j = startColumn[i]; j < startColumn[i + 1]; j++) {
        CoinFactorizationDouble value = element[j];
        CoinSimplexInt iRow = indexRow[j];
        assert(iRow < numberRows_);
        bool oldValue = (TEST_DOUBLE_REALLY_NONZERO(region[iRow]));
        CoinFactorizationDouble newValue = region[iRow] - value * pivotValue;
        if (oldValue) {
          if (newValue)
            region[iRow] = newValue;
          else
            region[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT;
        } else if (!TEST_LESS_THAN_TOLERANCE_REGISTER(newValue)) {
          region[iRow] = newValue;
          regionIndex[numberNonZero++] = iRow;
        }
      }
      region[putRow] = pivotValue;
    }
  }
  instrument_end();
  regionSparse->setNumElements(numberNonZero);
}
#endif
//  updateColumnTransposeR.  Updates part of column (FTRANR)
void CoinAbcTypeFactorization::updateColumnTransposeR(CoinIndexedVector *regionSparse
#if ABC_SMALL < 2
  ,
  CoinAbcStatistics &statistics
#endif
  ) const
{
  if (numberRowsExtra_ == numberRows_)
    return;
#if ABC_SMALL < 3
  CoinSimplexInt numberNonZero = regionSparse->getNumElements();
  if (numberNonZero) {
#endif
#if ABC_SMALL < 3
    const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_;
#endif
    // Size of R
    instrument_do("CoinAbcFactorizationTransposeR", startColumnRAddress_[numberR_]);
#if ABC_SMALL < 2
    if (startColumn[numberRowsExtra_]) {
#if ABC_SMALL >= 0
      if (numberNonZero < ((sparseThreshold_ << 2) * twiddleBtranFactor2())
        || (!numberL_ && gotLCopy() && gotRCopy())) {
#endif
        updateColumnTransposeRSparse(regionSparse);
        if (factorizationStatistics())
          statistics.countAfterR_ += regionSparse->getNumElements();
#if ABC_SMALL >= 0
      } else {
        updateColumnTransposeRDensish(regionSparse);
        // we have lost indices
        // make sure won't try and go sparse again
        if (factorizationStatistics())
          statistics.countAfterR_ += CoinMin((numberNonZero << 1), numberRows_);
        // temp +2 (was +1)
        regionSparse->setNumElements(numberRows_ + 2);
      }
#endif
    } else {
      if (factorizationStatistics())
        statistics.countAfterR_ += numberNonZero;
    }
#else
  updateColumnTransposeRDensish(regionSparse);
#if ABC_SMALL < 3
  // we have lost indices
  // make sure won't try and go sparse again
  // temp +2 (was +1)
  regionSparse->setNumElements(numberRows_ + 2);
#endif
#endif
#if ABC_SMALL < 3
  }
#endif
}
// Update partial Ftran by R update
void CoinAbcTypeFactorization::updatePartialUpdate(CoinIndexedVector &partialUpdate)
{
  CoinSimplexDouble *COIN_RESTRICT region = partialUpdate.denseVector();
  CoinSimplexInt *COIN_RESTRICT regionIndex = partialUpdate.getIndices();
  CoinSimplexInt numberNonZero = partialUpdate.getNumElements();
  const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_;
  const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_;
  const CoinSimplexInt *pivotRowBack = pivotColumnAddress_;
  const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_;
  CoinBigIndex start = startColumn[numberRowsExtra_ - 1];
  CoinBigIndex end = startColumn[numberRowsExtra_];
  CoinSimplexInt iRow = pivotRowBack[numberRowsExtra_ - 1];
  CoinFactorizationDouble pivotValue = region[iRow];
  for (CoinBigIndex j = start; j < end; j++) {
    CoinFactorizationDouble value = element[j];
    CoinSimplexInt jRow = indexRow[j];
    value *= region[jRow];
    pivotValue -= value;
  }
  if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) {
    if (!region[iRow])
      regionIndex[numberNonZero++] = iRow;
    region[iRow] = pivotValue;
  } else {
    if (region[iRow])
      region[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT;
  }
  partialUpdate.setNumElements(numberNonZero);
}
#if FACTORIZATION_STATISTICS
#ifdef ABC_JUST_ONE_FACTORIZATION
#define FACTORS_HERE
#endif
#ifdef FACTORS_HERE
double ftranTwiddleFactor1X = 1.0;
double ftranTwiddleFactor2X = 1.0;
double ftranFTTwiddleFactor1X = 1.0;
double ftranFTTwiddleFactor2X = 1.0;
double btranTwiddleFactor1X = 1.0;
double btranTwiddleFactor2X = 1.0;
double ftranFullTwiddleFactor1X = 1.0;
double ftranFullTwiddleFactor2X = 1.0;
double btranFullTwiddleFactor1X = 1.0;
double btranFullTwiddleFactor2X = 1.0;
double denseThresholdX = 31;
double twoThresholdX = 1000;
double minRowsSparse = 300;
double largeRowsSparse = 10000;
double mediumRowsDivider = 6;
double mediumRowsMinCount = 500;
double largeRowsCount = 1000;
#else
extern double ftranTwiddleFactor1X;
extern double ftranTwiddleFactor2X;
extern double ftranFTTwiddleFactor1X;
extern double ftranFTTwiddleFactor2X;
extern double btranTwiddleFactor1X;
extern double btranTwiddleFactor2X;
extern double ftranFullTwiddleFactor1X;
extern double ftranFullTwiddleFactor2X;
extern double btranFullTwiddleFactor1X;
extern double btranFullTwiddleFactor2X;
extern double denseThresholdX;
extern double twoThresholdX;
extern double minRowsSparse;
extern double largeRowsSparse;
extern double mediumRowsDivider;
extern double mediumRowsMinCount;
extern double largeRowsCount;
#endif
#else
#define minRowsSparse 300
#define largeRowsSparse 10000
#define mediumRowsDivider 6
#define mediumRowsMinCount 500
#define largeRowsCount 1000
#endif
//  makes a row copy of L
void CoinAbcTypeFactorization::goSparse2()
{
#if ABC_SMALL < 2
#if ABC_SMALL >= 0
  if (numberRows_ > minRowsSparse) {
#endif
    if (numberRows_ < largeRowsSparse) {
      sparseThreshold_ = CoinMin(numberRows_ / mediumRowsDivider, mediumRowsMinCount);
      sparseThreshold_ = CoinMin(numberRows_ / 6, 500);
    } else {
      sparseThreshold_ = CoinMax(largeRowsCount, numberRows_ >> 3);
      sparseThreshold_ = 500;
    }
#if FACTORIZATION_STATISTICS
    ftranTwiddleFactor1_ = ftranTwiddleFactor1X;
    ftranTwiddleFactor2_ = ftranTwiddleFactor2X;
    ftranFTTwiddleFactor1_ = ftranFTTwiddleFactor1X;
    ftranFTTwiddleFactor2_ = ftranFTTwiddleFactor2X;
    btranTwiddleFactor1_ = btranTwiddleFactor1X;
    btranTwiddleFactor2_ = btranTwiddleFactor2X;
    ftranFullTwiddleFactor1_ = ftranFullTwiddleFactor1X;
    ftranFullTwiddleFactor2_ = ftranFullTwiddleFactor2X;
    btranFullTwiddleFactor1_ = btranFullTwiddleFactor1X;
    btranFullTwiddleFactor2_ = btranFullTwiddleFactor2X;
#endif
    setYesGotLCopy();
    setYesGotUCopy();
    setYesGotSparse();
    // allow for stack, list, next, starts and char map of mark
    CoinSimplexInt nRowIndex = (numberRows_ + CoinSizeofAsInt(CoinSimplexInt) - 1) / CoinSizeofAsInt(char);
    CoinSimplexInt nInBig = static_cast< CoinSimplexInt >(sizeof(CoinBigIndex) / sizeof(CoinSimplexInt));
    assert(nInBig >= 1);
    sizeSparseArray_ = (2 + 2 * nInBig) * numberRows_ + nRowIndex;
    sparse_.conditionalNew(FACTOR_CPU * sizeSparseArray_);
    sparseAddress_ = sparse_.array();
    // zero out mark
    CoinAbcStack *stackList = reinterpret_cast< CoinAbcStack * >(sparseAddress_);
    listAddress_ = reinterpret_cast< CoinSimplexInt * >(stackList + numberRows_);
    markRowAddress_ = reinterpret_cast< CoinCheckZero * >(listAddress_ + numberRows_);
    assert(reinterpret_cast< CoinCheckZero * >(sparseAddress_ + (2 + 2 * nInBig) * numberRows_) == markRowAddress_);
    CoinAbcMemset0(markRowAddress_, nRowIndex);
#if ABC_PARALLEL
    //printf("PP 0__ %d %s\n",__LINE__,__FILE__);
    // convert to bytes
    sizeSparseArray_ *= sizeof(CoinSimplexInt);
    char *mark = reinterpret_cast< char * >(reinterpret_cast< char * >(markRowAddress_) + sizeSparseArray_);
    for (int i = 1; i < FACTOR_CPU; i++) {
      CoinAbcMemset0(mark, nRowIndex);
      mark = reinterpret_cast< char * >(reinterpret_cast< char * >(mark) + sizeSparseArray_);
    }
#endif
    elementByRowL_.conditionalDelete();
    indexColumnL_.conditionalDelete();
    startRowL_.conditionalNew(numberRows_ + 1);
    if (lengthAreaL_) {
      elementByRowL_.conditionalNew(lengthAreaL_);
      indexColumnL_.conditionalNew(lengthAreaL_);
    }
    elementByRowLAddress_ = elementByRowL_.array();
    indexColumnLAddress_ = indexColumnL_.array();
    startRowLAddress_ = startRowL_.array();
    // counts
    CoinBigIndex *COIN_RESTRICT startRowL = startRowLAddress_;
    CoinZeroN(startRowL, numberRows_);
    const CoinBigIndex *startColumnL = startColumnLAddress_;
    CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_;
    const CoinSimplexInt *indexRowL = indexRowLAddress_;
    for (CoinSimplexInt i = baseL_; i < baseL_ + numberL_; i++) {
      for (CoinBigIndex j = startColumnL[i]; j < startColumnL[i + 1]; j++) {
        CoinSimplexInt iRow = indexRowL[j];
        startRowL[iRow]++;
      }
    }
    const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_;
    // convert count to lasts
    CoinBigIndex count = 0;
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      CoinSimplexInt numberInRow = startRowL[i];
      count += numberInRow;
      startRowL[i] = count;
    }
    startRowL[numberRows_] = count;
    // now insert
    CoinFactorizationDouble *COIN_RESTRICT elementByRowL = elementByRowLAddress_;
    CoinSimplexInt *COIN_RESTRICT indexColumnL = indexColumnLAddress_;
    for (CoinSimplexInt i = baseL_ + numberL_ - 1; i >= baseL_; i--) {
#ifndef ABC_ORDERED_FACTORIZATION
      CoinSimplexInt iPivot = pivotLOrder[i];
#else
    CoinSimplexInt iPivot = i;
#endif
      for (CoinBigIndex j = startColumnL[i]; j < startColumnL[i + 1]; j++) {
        CoinSimplexInt iRow = indexRowL[j];
        CoinBigIndex start = startRowL[iRow] - 1;
        startRowL[iRow] = start;
        elementByRowL[start] = elementL[j];
        indexColumnL[start] = iPivot;
      }
    }
#if ABC_SMALL >= 0
  } else {
    sparseThreshold_ = 0;
    setNoGotLCopy();
    //setYesGotUCopy();
    setNoGotUCopy();
    setNoGotSparse();
  }
#endif
#endif
}

//  set sparse threshold
void
  CoinAbcTypeFactorization::sparseThreshold(CoinSimplexInt /*value*/)
{
  return;
#if 0
  if (value>0&&sparseThreshold_) {
    sparseThreshold_=value;
  } else if (!value&&sparseThreshold_) {
    // delete copy
    sparseThreshold_=0;
    elementByRowL_.conditionalDelete();
    startRowL_.conditionalDelete();
    indexColumnL_.conditionalDelete();
    sparse_.conditionalDelete();
  } else if (value>0&&!sparseThreshold_) {
    if (value>1)
      sparseThreshold_=value;
    else
      sparseThreshold_=0;
    goSparse();
  }
#endif
}
void CoinAbcTypeFactorization::maximumPivots(CoinSimplexInt value)
{
  if (value > 0) {
    if (numberRows_)
      maximumMaximumPivots_ = CoinMax(maximumMaximumPivots_, value);
    else
      maximumMaximumPivots_ = value;
    maximumPivots_ = value;
  }
  //printf("max %d maxmax %d\n",maximumPivots_,maximumMaximumPivots_);
}
void CoinAbcTypeFactorization::messageLevel(CoinSimplexInt value)
{
  if (value > 0 && value < 16) {
    messageLevel_ = value;
  }
}
// Reset all sparsity etc statistics
void CoinAbcTypeFactorization::resetStatistics()
{
#if ABC_SMALL < 2
  setStatistics(true);

  /// Below are all to collect
  ftranCountInput_ = 0.0;
  ftranCountAfterL_ = 0.0;
  ftranCountAfterR_ = 0.0;
  ftranCountAfterU_ = 0.0;
  ftranFTCountInput_ = 0.0;
  ftranFTCountAfterL_ = 0.0;
  ftranFTCountAfterR_ = 0.0;
  ftranFTCountAfterU_ = 0.0;
  btranCountInput_ = 0.0;
  btranCountAfterU_ = 0.0;
  btranCountAfterR_ = 0.0;
  btranCountAfterL_ = 0.0;
  ftranFullCountInput_ = 0.0;
  ftranFullCountAfterL_ = 0.0;
  ftranFullCountAfterR_ = 0.0;
  ftranFullCountAfterU_ = 0.0;
  btranFullCountInput_ = 0.0;
  btranFullCountAfterL_ = 0.0;
  btranFullCountAfterR_ = 0.0;
  btranFullCountAfterU_ = 0.0;

  /// We can roll over factorizations
  numberFtranCounts_ = 0;
  numberFtranFTCounts_ = 0;
  numberBtranCounts_ = 0;
  numberFtranFullCounts_ = 0;
  numberFtranFullCounts_ = 0;

  /// While these are averages collected over last
  ftranAverageAfterL_ = INITIAL_AVERAGE;
  ftranAverageAfterR_ = INITIAL_AVERAGE;
  ftranAverageAfterU_ = INITIAL_AVERAGE;
  ftranFTAverageAfterL_ = INITIAL_AVERAGE;
  ftranFTAverageAfterR_ = INITIAL_AVERAGE;
  ftranFTAverageAfterU_ = INITIAL_AVERAGE;
  btranAverageAfterU_ = INITIAL_AVERAGE;
  btranAverageAfterR_ = INITIAL_AVERAGE;
  btranAverageAfterL_ = INITIAL_AVERAGE;
  ftranFullAverageAfterL_ = INITIAL_AVERAGE;
  ftranFullAverageAfterR_ = INITIAL_AVERAGE;
  ftranFullAverageAfterU_ = INITIAL_AVERAGE;
  btranFullAverageAfterL_ = INITIAL_AVERAGE;
  btranFullAverageAfterR_ = INITIAL_AVERAGE;
  btranFullAverageAfterU_ = INITIAL_AVERAGE;
#endif
}
// See if worth going sparse
void CoinAbcTypeFactorization::checkSparse()
{
#if ABC_SMALL < 2
  // See if worth going sparse and when
  if (numberFtranCounts_ > 50) {
    ftranCountInput_ = CoinMax(ftranCountInput_, 1.0);
    ftranAverageAfterL_ = CoinMax(ftranCountAfterL_ / ftranCountInput_, INITIAL_AVERAGE2);
    ftranAverageAfterR_ = CoinMax(ftranCountAfterR_ / ftranCountAfterL_, INITIAL_AVERAGE2);
    ftranAverageAfterU_ = CoinMax(ftranCountAfterU_ / ftranCountAfterR_, INITIAL_AVERAGE2);
    ftranFTCountInput_ = CoinMax(ftranFTCountInput_, INITIAL_AVERAGE2);
    ftranFTAverageAfterL_ = CoinMax(ftranFTCountAfterL_ / ftranFTCountInput_, INITIAL_AVERAGE2);
    ftranFTAverageAfterR_ = CoinMax(ftranFTCountAfterR_ / ftranFTCountAfterL_, INITIAL_AVERAGE2);
    ftranFTAverageAfterU_ = CoinMax(ftranFTCountAfterU_ / ftranFTCountAfterR_, INITIAL_AVERAGE2);
    if (btranCountInput_ && btranCountAfterU_ && btranCountAfterR_) {
      btranAverageAfterU_ = CoinMax(btranCountAfterU_ / btranCountInput_, INITIAL_AVERAGE2);
      btranAverageAfterR_ = CoinMax(btranCountAfterR_ / btranCountAfterU_, INITIAL_AVERAGE2);
      btranAverageAfterL_ = CoinMax(btranCountAfterL_ / btranCountAfterR_, INITIAL_AVERAGE2);
    } else {
      // we have not done any useful btrans (values pass?)
      btranAverageAfterU_ = INITIAL_AVERAGE2;
      btranAverageAfterR_ = INITIAL_AVERAGE2;
      btranAverageAfterL_ = INITIAL_AVERAGE2;
      btranFullCountAfterL_ = INITIAL_AVERAGE2;
      btranFullCountAfterR_ = INITIAL_AVERAGE2;
      btranFullCountAfterU_ = INITIAL_AVERAGE2;
    }
    ftranFullCountInput_ = CoinMax(ftranFullCountInput_, 1.0);
    ftranFullAverageAfterL_ = CoinMax(ftranFullCountAfterL_ / ftranFullCountInput_, INITIAL_AVERAGE2);
    ftranFullAverageAfterR_ = CoinMax(ftranFullCountAfterR_ / ftranFullCountAfterL_, INITIAL_AVERAGE2);
    ftranFullAverageAfterU_ = CoinMax(ftranFullCountAfterU_ / ftranFullCountAfterR_, INITIAL_AVERAGE2);
    btranFullCountInput_ = CoinMax(btranFullCountInput_, 1.0);
    btranFullAverageAfterL_ = CoinMax(btranFullCountAfterL_ / btranFullCountInput_, INITIAL_AVERAGE2);
    btranFullAverageAfterR_ = CoinMax(btranFullCountAfterR_ / btranFullCountAfterL_, INITIAL_AVERAGE2);
    btranFullAverageAfterU_ = CoinMax(btranFullCountAfterU_ / btranFullCountAfterR_, INITIAL_AVERAGE2);
  }
  // scale back

  ftranCountInput_ *= AVERAGE_SCALE_BACK;
  ftranCountAfterL_ *= AVERAGE_SCALE_BACK;
  ftranCountAfterR_ *= AVERAGE_SCALE_BACK;
  ftranCountAfterU_ *= AVERAGE_SCALE_BACK;
  ftranFTCountInput_ *= AVERAGE_SCALE_BACK;
  ftranFTCountAfterL_ *= AVERAGE_SCALE_BACK;
  ftranFTCountAfterR_ *= AVERAGE_SCALE_BACK;
  ftranFTCountAfterU_ *= AVERAGE_SCALE_BACK;
  btranCountInput_ *= AVERAGE_SCALE_BACK;
  btranCountAfterU_ *= AVERAGE_SCALE_BACK;
  btranCountAfterR_ *= AVERAGE_SCALE_BACK;
  btranCountAfterL_ *= AVERAGE_SCALE_BACK;
  ftranFullCountInput_ *= AVERAGE_SCALE_BACK;
  ftranFullCountAfterL_ *= AVERAGE_SCALE_BACK;
  ftranFullCountAfterR_ *= AVERAGE_SCALE_BACK;
  ftranFullCountAfterU_ *= AVERAGE_SCALE_BACK;
  btranFullCountInput_ *= AVERAGE_SCALE_BACK;
  btranFullCountAfterL_ *= AVERAGE_SCALE_BACK;
  btranFullCountAfterR_ *= AVERAGE_SCALE_BACK;
  btranFullCountAfterU_ *= AVERAGE_SCALE_BACK;
#endif
}
// Condition number - product of pivots after factorization
CoinSimplexDouble
CoinAbcTypeFactorization::conditionNumber() const
{
  CoinSimplexDouble condition = 1.0;
  const CoinFactorizationDouble *pivotRegion = pivotRegionAddress_;
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
    condition *= pivotRegion[i];
  }
  condition = CoinMax(fabs(condition), 1.0e-50);
  return 1.0 / condition;
}
#ifndef NDEBUG
void CoinAbcTypeFactorization::checkMarkArrays() const
{
  CoinCheckZero *COIN_RESTRICT mark = markRowAddress_;
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
    assert(!mark[i]);
  }
#if ABC_PARALLEL
  mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + sizeSparseArray_);
  for (CoinSimplexInt i = 0; i < numberRows_; i++) {
    assert(!mark[i]);
  }
  for (int i = 1; i < FACTOR_CPU; i++) {
    for (CoinSimplexInt i = 0; i < numberRows_; i++) {
      assert(!mark[i]);
    }
    mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + sizeSparseArray_);
  }
#endif
}
#endif
#endif

/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/
